Reonic Residential Projects API

Residential customer projects across the request, offer, and installation lifecycle stages.

OpenAPI Specification

reonic-residential-projects-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Reonic REST Api v3 Activities Residential Projects 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: Residential Projects
  description: Residential customer projects across the request, offer, and installation lifecycle stages.
paths:
  /residentialProjects:
    get:
      summary: List residential projects
      description: 'List residential projects across all lifecycle stages (request, offer, installation) in a paginated format. Use the `stage` query param to restrict to one or more stages; omit to span all three.


        **Examples:**

        - Most recent offers: `GET /residentialProjects?stage=offer&sort=-offerCreatedAt&page=1`

        - Open offers: `GET /residentialProjects?stage=offer&dealState=Open`

        - Projects assigned to specific Kanban columns: `GET /residentialProjects?kanbanColumnIds=<uuid>&kanbanColumnIds=<uuid>`


        **Allowed API keys:** Read-only, Read and Write'
      tags:
      - Residential Projects
      parameters:
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            enum:
            - request
            - offer
            - installation
          maxItems: 3
          description: 'Filter by lifecycle stages: request, offer, installation. Omit to include all stages.'
          examples:
          - request
          - offer,installation
        required: false
        description: 'Filter by lifecycle stages: request, offer, installation. Omit to include all stages.'
        name: stage
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            enum:
            - Open
            - Won
            - Lost
          maxItems: 3
          description: Filter by deal state. Omit to include all. Pass `null` to return only projects that have no deal state.
          examples:
          - Open
          - Won,Lost
        required: false
        description: Filter by deal state. Omit to include all. Pass `null` to return only projects that have no deal state.
        name: dealState
        in: query
      - schema:
          type: string
          enum:
          - exclude
          - include
          - only
          default: exclude
          description: 'Controls whether archived projects appear in results. Default: exclude.'
        required: false
        description: 'Controls whether archived projects appear in results. Default: exclude.'
        name: archived
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            format: uuid
          maxItems: 50
          description: Filter projects that are tagged with any of the specified tag IDs. Pass `null` to return only projects that have no tags.
        required: false
        description: Filter projects that are tagged with any of the specified tag IDs. Pass `null` to return only projects that have no tags.
        name: tagIds
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            format: uuid
          maxItems: 50
          description: Filter projects that have a lead source with any of the specified IDs. Pass `null` to return only projects that have no lead source.
        required: false
        description: Filter projects that have a lead source with any of the specified IDs. Pass `null` to return only projects that have no lead source.
        name: leadSourceIds
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            format: uuid
          maxItems: 50
          description: Filter projects that are in any of the specified Kanban boards. Pass `null` to return only projects that are not assigned to any Kanban board. Mutually exclusive with `kanbanColumnIds`.
        required: false
        description: Filter projects that are in any of the specified Kanban boards. Pass `null` to return only projects that are not assigned to any Kanban board. Mutually exclusive with `kanbanColumnIds`.
        name: kanbanBoardIds
        in: query
      - schema:
          type:
          - array
          - 'null'
          items:
            type: string
            format: uuid
          maxItems: 50
          description: Filter projects that are in any of the specified Kanban columns. Pass `null` to return only projects that have no status assigned (the "no status" column). Mutually exclusive with `kanbanBoardIds`.
        required: false
        description: Filter projects that are in any of the specified Kanban columns. Pass `null` to return only projects that have no status assigned (the "no status" column). Mutually exclusive with `kanbanBoardIds`.
        name: kanbanColumnIds
        in: query
      - schema:
          type: string
          minLength: 1
          maxLength: 1000
          description: Filter projects by their exact internal customer number (e.g. from your CRM or ERP).
        required: false
        description: Filter projects by their exact internal customer number (e.g. from your CRM or ERP).
        name: customerNumber
        in: query
      - schema:
          type: string
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
          description: Filter projects whose customer contact has this ID. Reference to [**Contacts**](#tag/contacts)
        required: false
        description: Filter projects whose customer contact has this ID. Reference to [**Contacts**](#tag/contacts)
        name: contactId
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where projectCreatedAt is after this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where projectCreatedAt is after this datetime (exclusive)
        name: projectCreatedAt.gt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where projectCreatedAt is before this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where projectCreatedAt is before this datetime (exclusive)
        name: projectCreatedAt.lt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where requestCreatedAt is after this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where requestCreatedAt is after this datetime (exclusive)
        name: requestCreatedAt.gt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where requestCreatedAt is before this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where requestCreatedAt is before this datetime (exclusive)
        name: requestCreatedAt.lt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where offerCreatedAt is after this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where offerCreatedAt is after this datetime (exclusive)
        name: offerCreatedAt.gt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where offerCreatedAt is before this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where offerCreatedAt is before this datetime (exclusive)
        name: offerCreatedAt.lt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where installationCreatedAt is after this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where installationCreatedAt is after this datetime (exclusive)
        name: installationCreatedAt.gt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where installationCreatedAt is before this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where installationCreatedAt is before this datetime (exclusive)
        name: installationCreatedAt.lt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where updatedAt is after this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where updatedAt is after this datetime (exclusive)
        name: updatedAt.gt
        in: query
      - schema:
          type:
          - string
          - 'null'
          format: date-time
          description: Filter records where updatedAt is before this datetime (exclusive)
          example: '2026-01-01T15:30:00.000Z'
        required: false
        description: Filter records where updatedAt is before this datetime (exclusive)
        name: updatedAt.lt
        in: query
      - schema:
          type: integer
          minimum: 1
          default: 1
          description: 'Page number, starting from 1. Default: 1.'
        required: false
        description: 'Page number, starting from 1. Default: 1.'
        name: page
        in: query
      - schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
          description: 'Number of items per page. Default: 50. Max: 200.'
        required: false
        description: 'Number of items per page. Default: 50. Max: 200.'
        name: itemsPerPage
        in: query
      - schema:
          type:
          - string
          - 'null'
          default: -projectCreatedAt
          description: 'Sort order. Use field names for ascending (e.g. "createdAt"), minus sign for descending (e.g. "-createdAt"). Chain with commas (e.g. "createdAt,editedAt"). Sortable fields: projectCreatedAt, requestCreatedAt, offerCreatedAt, installationCreatedAt, updatedAt. Defaults to -projectCreatedAt.'
          examples:
          - -projectCreatedAt
          - offerCreatedAt
          - -updatedAt
        required: false
        description: 'Sort order. Use field names for ascending (e.g. "createdAt"), minus sign for descending (e.g. "-createdAt"). Chain with commas (e.g. "createdAt,editedAt"). Sortable fields: projectCreatedAt, requestCreatedAt, offerCreatedAt, installationCreatedAt, updatedAt. Defaults to -projectCreatedAt.'
        name: sort
        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: Paginated list of residential projects
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ResidentialProject'
                  pagination:
                    type: object
                    properties:
                      page:
                        type: integer
                        minimum: 1
                        description: Current page number
                      perPage:
                        type: integer
                        minimum: 1
                        description: Number of items per page
                      total:
                        type: integer
                        minimum: 0
                        description: Total number of items across all pages
                      totalPages:
                        type: integer
                        minimum: 1
                      next:
                        type:
                        - string
                        - 'null'
                        description: Path to the next page, or null if there is no next page
                      prev:
                        type:
                        - string
                        - 'null'
                        description: Path to the previous page, or null if there is no previous page
                    required:
                    - page
                    - perPage
                    - total
                    - totalPages
                    - next
                    - prev
                required:
                - data
                - pagination
  /residentialProjects/{projectId}:
    get:
      summary: Get residential project
      description: 'Get a single residential project by its ID. Works for any stage (request, offer, or installation).


        **Allowed API keys:** Read-only, Read and Write'
      tags:
      - Residential Projects
      parameters:
      - schema:
          type: string
          format: uuid
        required: true
        name: projectId
        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 residential project
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResidentialProjectDetail'
  /residentialProjects/create:
    post:
      summary: Create residential project
      description: 'Create a residential project at a given lifecycle stage.


        **Allowed API keys:** Read and Write, Lead creation only'
      tags:
      - Residential Projects
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                stage:
                  type: string
                  enum:
                  - request
                  - offer
                  - installation
                latLng:
                  type: object
                  properties:
                    lat:
                      type: number
                      minimum: -90
                      maximum: 90
                      example: 48.363767359
                    lng:
                      type: number
                      minimum: -180
                      maximum: 180
                      example: 10.888136991
                  required:
                  - lat
                  - lng
                  additionalProperties: false
                  description: Coordinates of the installation site. Provide either `latLng` or `address` (exactly one). The project's `address` in the response is reverse-geocoded from these coordinates. Note that this is independent of the customer contact's address — if you also send `customerContact.address`, that address is stored on the contact and may differ from the geocoded installation address (e.g. when the customer's residence differs from the installation site).
                address:
                  type: object
                  properties:
                    street:
                      type: string
                      minLength: 1
                      maxLength: 1000
                      example: Hauptstraße
                    houseNumber:
                      type: string
                      minLength: 1
                      maxLength: 1000
                      example: '12'
                    postcode:
                      type: string
                      minLength: 1
                      maxLength: 1000
                      example: '86150'
                    city:
                      type: string
                      minLength: 1
                      maxLength: 1000
                      example: Augsburg
                    country:
                      type: string
                      enum:
                      - Austria
                      - Switzerland
                      - Germany
                      - Liechtenstein
                      - Luxembourg
                      - Czechia
                      - Slovakia
                      - Hungary
                      - Poland
                      - Slovenia
                      - France
                      - Belgium
                      - Netherlands
                      - Monaco
                      - Andorra
                      - Italy
                      - SanMarino
                      - VaticanCity
                      - Malta
                      - Spain
                      - Portugal
                      - Gibraltar
                      - Denmark
                      - Sweden
                      - Norway
                      - Finland
                      - Iceland
                      - FaroeIslands
                      - Greenland
                      - Albania
                      - Armenia
                      - Azerbaijan
                      - Belarus
                      - BosniaAndHerzegovina
                      - Bulgaria
                      - Croatia
                      - Cyprus
                      - Estonia
                      - Georgia
                      - Greece
                      - Kazakhstan
                      - Kosovo
                      - Latvia
                      - Lithuania
                      - Moldova
                      - Montenegro
                      - NorthMacedonia
                      - Romania
                      - Russia
                      - Serbia
                      - Turkey
                      - Ukraine
                      - UnitedKingdom
                      - Jersey
                      - Ireland
                      - Martinique
                      - Guadeloupe
                      - Reunion
                      - SaintMartin
                      - SaintBarthelemy
                      - SaintPierreAndMiquelon
                      - FrenchGuiana
                      - Bahamas
                      - Barbados
                      - Dominica
                      - Grenada
                      - Jamaica
                      - SaintKittsAndNevis
                      - SaintLucia
                      - SaintVincentAndTheGrenadines
                      - TrinidadAndTobago
                      - AntiguaAndBarbuda
                      - Aruba
                      - Curacao
                      - Bermuda
                      - CaymanIslands
                      - TurksAndCaicosIslands
                      - Anguilla
                      - Montserrat
                      - BritishVirginIslands
                      - USVirginIslands
                      - SintMaarten
                      - BonaireSintEustatiusSaba
                      - Argentina
                      - Bolivia
                      - Belize
                      - Brazil
                      - Chile
                      - Colombia
                      - CostaRica
                      - Cuba
                      - DominicanRepublic
                      - Ecuador
                      - ElSalvador
                      - Guatemala
                      - Guyana
                      - Honduras
                      - Haiti
                      - Mexico
                      - Nicaragua
                      - Panama
                      - Paraguay
                      - Peru
                      - Suriname
                      - Uruguay
                      - Venezuela
                      - FalklandIslands
                      - UnitedStates
                      - Morocco
                      - SouthAfrica
                      example: Germany
                  required:
                  - street
                  - postcode
                  - city
                  - country
                  additionalProperties: false
                  description: Installation site address, geocoded into coordinates. Provide either `latLng` or `address` (exactly one). Only a precise, street-level match whose resolved postcode equals the `postcode` you sent sets the coordinates; if the address can only be resolved approximately (e.g. to a city, postcode, or country), resolves to a different postcode, or cannot be geocoded at all, the coordinates default to `0, 0`.
                customerContact:
                  anyOf:
                  - $ref: '#/components/schemas/ContactReference'
                  - $ref: '#/components/schemas/ContactCreate'
                  description: Either reference an existing contact by `id` or provide full contact details to create a new one.
                name:
                  type: string
                  minLength: 2
                  maxLength: 500
                  description: If omitted defaults to customer contacts `firstName` + `lastName`
                  example: Test Project
                customerNumber:
                  type: string
                  maxLength: 1000
                  description: Internal customer reference, e.g. from your CRM or ERP.
                  example: C-1042
                meterNumber:
                  type: string
                  maxLength: 1000
                  description: Electricity meter number at the customer's property.
                  example: 1APA0123456789
                kanbanBoardId:
                  type:
                  - string
                  - 'null'
                  format: uuid
                  example: 123e4567-e89b-12d3-a456-426614174000
                  description: ID of the Kanban board this project should be placed on. Has to match `stage`. The project is placed in the board's first column. Mutually exclusive with `kanbanColumnId`.
                kanbanColumnId:
                  type:
                  - string
                  - 'null'
                  format: uuid
                  example: 123e4567-e89b-12d3-a456-426614174000
                  description: ID of the project's current Kanban column. Has to match `stage`. Reference to [**Kanban Columns**](#tag/kanban-columns). Mutually exclusive with `kanbanBoardId`.
                leadSourceId:
                  type:
                  - string
                  - 'null'
                  format: uuid
                  example: 123e4567-e89b-12d3-a456-426614174000
                tagIds:
                  type: array
                  items:
                    type: string
                    format: uuid
                  maxItems: 50
                  description: IDs of the tags to assign to this project. Reference to [**Tags**](#tag/tags)
                  example:
                  - 123e4567-e89b-12d3-a456-426614174000
                  - 123e4567-e89b-12d3-a456-426614174002
                packages:
                  type: object
                  properties:
                    solarPackageId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                      example: 123e4567-e89b-12d3-a456-426614174000
                    batteryStoragePackageId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                      example: 123e4567-e89b-12d3-a456-426614174000
                    evChargerPackageId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                      example: 123e4567-e89b-12d3-a456-426614174000
                    heatingPackageId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                      example: 123e4567-e89b-12d3-a456-426614174000
                  additionalProperties: false
                integrations:
                  type: object
                  properties:
                    hubspotDealId:
                      type:
                      - string
                      - 'null'
                      maxLength: 1000
                    pipedriveDealId:
                      type:
                      - integer
                      - 'null'
                      minimum: 1
                      maximum: 9007199254740991
                    weclappOpportunityId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                    bitrixDealId:
                      type:
                      - string
                      - 'null'
                      maxLength: 1000
                    photovateDealId:
                      type:
                      - string
                      - 'null'
                      format: uuid
                  additionalProperties: false
                  description: IDs of this project in third-party systems.
              required:
              - stage
              - customerContact
              additionalProperties: false
      responses:
        '201':
          description: The created residential project
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResidentialProjectDetail'
  /residentialProjects/{projectId}/update:
    post:
      summary: Update residential project
      description: 'Update fields of a residential project. Stage-agnostic — the same fields are editable at any lifecycle stage. If you want to update contact details, use the dedicated endpoint — see [**Contacts**](#tag/contacts) for more details on that.


        **Allowed API keys:** Read and Write'
      tags:
      - Residential Projects
      parameters:
      - schema:
          type: string
          format: uuid
        required: true
        name: projectId
        in: path
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                stage:
                  type: string
                  enum:
                  - request
                  - offer
                  - installation
                latLng:
                  type: object
                  properties:
                    lat:
                      type: number
                      minimum: -90
                      maximum: 90
                      example: 48.363767359
                    lng:
                      type: number
                      minimum: -180
                      maximum: 180
                      example: 10.888136991
                  required:
                  - lat
                  - lng
                  additionalProperties: false
                  description: Updates the coordinates of the installation site. The project's `address` in the response is reverse-geocoded from these coordinates and will reflect the new location on subsequent reads. The customer contact's own address is stored separately and is not affected by this update.
                name:
                  type: string
                  minLength: 2
                  maxLength: 500
                customerNumber:
                  type:
                  - string
                  - 'null'
                  maxLength: 1000
                  description: Internal customer reference, e.g. from your CRM or ERP. Pass `null` to clear.
                  example: C-1042
                meterNumber:
                  type:
                  - string
                  - 'null'
                  maxLength: 1000
                  description: Electricity meter number at the customer's property. Pass `null` to clear.
                  example: 1APA0123456789
                targetSignatureDate:
                  type:
                  - string
                  - 'null'
                  format: date-time
                  example: '2026-01-01T15:30:00.000Z'
                  description: Target date by which the offer should be signed. Pass `null` to clear.
                closedAt:
                  type:
                  - string
    

# --- truncated at 32 KB (93 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/reonic/refs/heads/main/openapi/reonic-residential-projects-api-openapi.yml