Label-wise API

Enter your password to access the documentation.

Incorrect password. Please try again.

Label-wise API

Deliver a complete project to Label-wise as a single JSON file, or add measured geometry to a project an EP advisor already has open. This page describes the file format and the two API calls around it.

Log in with your own credentials at app.label-wise.nl/version-test to check the data you delivered. Questions: support@label-wise.nl.

How it works

Your software writes a JSON file; the EP advisor imports it in Label-wise. Everything in the file — the project, the object, the calculation zones, the surfaces, the constructions and the photos — is created in one step, in the right order, with the correct links between the records.

Why a file and not a chain of API calls? A project is a hierarchy: constructions must exist before surfaces can point at them, a calculation zone before its surfaces, and every record references the one above it. Chaining that through separate calls means juggling returned ids, and leaves half-built projects behind when one call fails midway. The import reads the whole file first, refuses it if anything is wrong, and only then writes. A project is either complete, or not created at all.

To deliver a project you need nothing but the file — it carries everything required to create the project, and you authenticate with your API token.

Authorization: Bearer <your-token>
StepWhatWhen
1Retrieve enum valuesGET /wf/enums_internal_values_externalOnce, when you build your integration. Several fields in the file only accept values from this list.
2Deliver the JSON filePer project. The advisor imports it in Label-wise.
3Find userPOST /wf/find_userOnce per EP advisor, and only if you want to retrieve dossiers later.
4Retrieve the dossierGET /wf/object_dossierOptional, after the intake. Pulls the photos and documents back into your own system.

Steps 3 and 4 are only needed when you want data back out of Label-wise.

Two flows

There are two kinds of import file. The meta.formaat field tells Label-wise which one it is getting, and that determines what has to be in the file.

Whole projectGeometry only
meta.formaatlabelwise-projectlabelwise-geometrie
Use it whenYou deliver a complete intake: project, client, address, geometryYou only measure. The advisor already has the object open in Label-wise
Imported fromThe projects overview — the project does not exist yetInside the object, at the Rekenzones step
CreatesProject + object + zones + surfaces + constructionsZones + surfaces + constructions only
The file containsmeta + project + rekenzones (or objecten[], see below)meta + rekenzones
Project, client and addressIn the fileAlready in Label-wise — you supply nothing

Everything below rekenzones is identical in both. Only the block at the top differs — so if you support one flow, the other is a small step.

Whole project

meta.formaat is labelwise-project. Use this when you deliver an entire intake and the project does not exist in Label-wise yet.

A complete example

{
  "meta": { "formaat": "labelwise-project", "versie": "1.0", "bron": "YourSoftware 4.2" },

  "project": {
    "projectnaam": "Voorbeeldproject met eengezinswoning",
    "objecttype": "RESIDENTIAL",
    "bouwfase": "EXISTING_BUILDING",
    "opname": "BASIC",
    "type_opname": "RESIDENTIAL_BASIC",
    "enkele_opname": true,
    "bouwjaar_algemeen": 2021,

    "object_adres_straat": "Haringburgwal",
    "object_adres_huisnummer": "11",
    "object_adres_postcode": "1141AT",
    "object_adres_woonplaats": "Monnickendam",
    "gebouwhoogte": 10.85,

    "gebouwtype": "SINGLE_FAMILY",
    "subtype": "SEMI_DETACHED",

    "opdrachtgever_voornaam": "Jack",
    "opdrachtgever_achternaam": "de Vries",
    "opdrachtgever_email": "jack@voorbeeld.nl",
    "opdrachtgever_telefoonnummer": "06123456789"
  },

  "rekenzones": [
    {
      "naam": "Algemene rekenzone, hele woning",
      "verdiepingen": [
        { "gebruiksoppervlakte_m2": 48 },
        { "gebruiksoppervlakte_m2": 48 }
      ],
      "constructies": [
        { "id": "gevels", "naam": "Gevels basiswoning", "bouwdeeltype": "FACADE", "rc_waarde": 6 },
        { "id": "vloer",  "naam": "Vloer basiswoning",  "bouwdeeltype": "FLOOR", "rc_waarde": 6 },
        { "id": "ramen",  "naam": "Ramen voorgevel",    "bouwdeeltype": "WINDOW",
          "u_waarde": 1.4, "g_waarde": 0.6 }
      ],
      "hoofdvlakken": [
        {
          "id": "zuid-gevel",
          "naam": "Zuid gevel",
          "bouwdeeltype": "FACADE",
          "bruto_oppervlakte_m2": 43.2,
          "netto_oppervlakte_m2": 37.2,
          "breedte_m": 8,
          "hoogte_of_lengte_m": 5.4,
          "grenst_aan": "OUTSIDE",
          "orientatie": "SOUTH(180)",
          "locatie": "FRONT_FACADE",
          "constructie_id": "gevels",
          "deelvlakken": [
            { "id": "zuid-gevel-raam-1", "naam": "Raam", "type": "WINDOW",
              "oppervlakte_m2": 6, "breedte_m": 3, "hoogte_m": 2, "constructie_id": "ramen" }
          ]
        },
        {
          "id": "vloer-begane-grond",
          "naam": "Vloer begane grond",
          "bouwdeeltype": "FLOOR",
          "bruto_oppervlakte_m2": 48,
          "netto_oppervlakte_m2": 48,
          "grenst_aan": "GROUND",
          "locatie": "FLOORS",
          "constructie_id": "vloer"
        }
      ]
    }
  ]
}

The example above is abridged. The complete file — seven surfaces, five constructions, two stories and eleven photos and documents — is the same file the import screen in Label-wise offers, and you can grab it here:

Download the complete examplevoorbeeld-import-project.json · 13 kB

meta

FieldTypeRequiredDescription
formaattextExactly "labelwise-project". The signature Label-wise recognises the file by.
versietext"1.0".
brontextName of the software that wrote the file — your own product name. Label-wise records it with the import, so a file can always be traced back to where it came from. A file without it is refused.
aangemaakt_opdate (YYYY-MM-DD)Creation date.

project

Creates the project, the object and the address in one go.

FieldTypeRequiredDescription
projectnaamtextName of the project / intake.
objecttypeenum ObjectTypeRESIDENTIAL or UTILITY.
bouwfaseenum BuildingPhaseEXISTING_BUILDING · NEW_BUILDING · BUILDING_NOTICE.
opnameenum RecordTypeBASIC or DETAILED.
type_opnameenum IntakeTypeRESIDENTIAL_BASIC · RESIDENTIAL_DETAILED · UTILITY_BASIC · UTILITY_DETAILED. Must match objecttype + opname.
enkele_opnamebooleantrue = standalone intake, false = part of a combined intake.
bouwjaar_algemeennumberConstruction year of the building. Also used as the construction year of every calculation zone.
renovatiejaar_algemeennumberYear of renovation, if applicable. Also used for every calculation zone.
object_adres_straat · _huisnummer · _huisnummertoevoeging · _postcode · _woonplaatstextAddress of the object. Supply it: Label-wise looks up the BAG identifiers and the map position from it after the import, and the composed address is what you search on to retrieve the dossier. Write the postcode without a space (1141AT).
opdrachtgever_voornaam · _achternaam · _email · _bedrijf · _telefoonnummertextClient details.
gebouwhoogtenumberIn metres.
gebouwtypeenum Buildingtype
subtypeenum BuildingSubtype
liggingenum LocationInBuilding
daktypeenum RoofType

Several objects in one file

A project can hold more than one object — a row of houses, a block of flats, a portfolio measured in one visit. They share the project, the client and the intake settings; everything else differs per object, starting with the address.

For that case the file gets one extra layer: objecten[]. The project block stays exactly where it is and is written once. Everything that belongs to a single object moves into the list: its name, its address, its building classification, its rekenzones and its dossier.

{
  "meta": { "formaat": "labelwise-project", "versie": "1.0", "bron": "YourSoftware 4.2" },

  "project": {
    "projectnaam": "Rij Baakhoven",
    "objecttype": "RESIDENTIAL",
    "bouwfase": "EXISTING_BUILDING",
    "opname": "BASIC",
    "type_opname": "RESIDENTIAL_BASIC",
    "enkele_opname": false,
    "bouwjaar_algemeen": 1902,
    "opdrachtgever_achternaam": "Woningstichting Susteren"
  },

  "objecten": [
    {
      "objectnaam": "Baakhoven 4",
      "object_adres_straat": "Baakhoven",
      "object_adres_huisnummer": "4",
      "object_adres_postcode": "6114RJ",
      "object_adres_woonplaats": "Susteren",
      "gebouwtype": "SINGLE_FAMILY",
      "subtype": "CORNER",
      "rekenzones": [ /* … as described below … */ ],
      "dossier": [ /* … photos of this object … */ ]
    },
    {
      "objectnaam": "Baakhoven 6",
      "object_adres_straat": "Baakhoven",
      "object_adres_huisnummer": "6",
      "object_adres_postcode": "6114RJ",
      "object_adres_woonplaats": "Susteren",
      "subtype": "IN_BETWEEN",
      "rekenzones": [ /* … */ ]
    }
  ]
}

The form without objecten[] stays valid. A file that puts the object fields straight on project and rekenzones at the top level — the form described above, and the only form there was until now — keeps working exactly as it does today. There is nothing to change and no deadline: leaving out objecten[] simply means the file holds one object, which is what the vast majority of intakes are. Only reach for the extra layer when you actually deliver more than one object in one file.

Which fields move into an object: objectnaam · objecttype · object_adres_straat · _huisnummer · _huisnummertoevoeging · _postcode · _woonplaats · bouwjaar_algemeen · renovatiejaar_algemeen · gebouwtype · subtype · ligging · daktype · gebouwhoogte · notities · plus that object's rekenzones and dossier. Their meaning is unchanged — see the project table above. Everything else stays on project and applies to the whole file.

Each object gets its own address. Two objects cannot share one: the address record hangs under the object, not under the project. So supply the address per entry, even when the objects sit next to each other in the same street.

How a series is imported

Worth knowing, because it shows in the timing. The import processes one object per call. Measured over 343 real objects, one object costs around 65 API calls; a hundred objects is roughly 6,500, and that does not fit in a single request — it would be cut off halfway, with fifty objects created and fifty not, and no way to tell which.

So Label-wise imports object 0, reports what is left, and schedules itself again for object 1:

FieldDirectionMeaning
object_indexinWhich entry of objecten[] this call handles. Defaults to 0.
aantal_objectenoutHow many objects the file contains.
volgende_indexoutThe index of the next object, or -1 when this was the last one — or when the call failed.

A backend workflow reschedules itself as long as volgende_index is above -1 and the status is ok, with a short pause in between. Four things follow from that, and they are the reason it is built this way: run time is no longer a ceiling, because every call is as heavy as an ordinary single-object import; the load at any moment stays what it is today; the pause sits where it belongs, between objects; and the run is restartable — if object 57 fails, the series stops there with an honest message and you resume from 57 instead of redoing everything.

Your side of it does not change: you deliver one file, whatever it contains.

Geometry only

meta.formaat is labelwise-geometrie. Use this when you only measure.

The advisor starts this import from inside the object, at the Rekenzones step. Everything around the geometry already exists there — the project, the object, the address, the client — and Label-wise passes that context along with the upload. You supply none of it.

So the file is the whole-project file minus the top: meta and rekenzones, nothing else. No object is created, nothing existing is overwritten; the zones, surfaces and constructions are added to the object that is already open.

{
  "meta": { "formaat": "labelwise-geometrie", "versie": "1.0", "bron": "YourSoftware 4.2" },
  "rekenzones": [ /* identical to the whole-project flow */ ]
}

The geometry

Everything below is identical in both flows.

rekenzones[]

At least one. A calculation zone groups the surfaces that share one thermal zone; a file may contain several.

FieldTypeRequiredDescription
naamtextDisplay name of the zone.
externe_idtextYour own reference. Stored for traceability.
constructieslistThe constructions used in this zone.
hoofdvlakkenlistThe main surfaces.
verdiepingenlistUsable floor area per story: { "gebruiksoppervlakte_m2": 48 }. One entry per story; the total is calculated from it.
qv10_gemetenbooleanAir permeability measured?
qv10_waardenumberMeasured qv10 value.
bouwwijze_vloerenenum FloorConstructionTypeLIGHT · HEAVY · VERY_HEAVY.
bouwwijze_wandenenum WallConstructionTypeLIGHT · HEAVY · VERY_HEAVY.
plafondenum CeilingTypeCLOSED_OR_LOW · NONE_OR_OPEN.
aantal_bouwlagennumberNumber of stories.

constructies[]

A construction describes the thermal quality of a building part. Every surface points at one through constructie_id.

id is the key, code is the BCRG code. They are two different things. id only exists to link surfaces to constructions inside this file — pick anything readable. code is the BCRG code of the quality declaration: real data that is stored on the construction, and it does not have to be unique. Do not use code to link with; several constructions may legitimately carry the same one.

Constructions belong to the project, not to a single calculation zone: they end up on the project and are de-duplicated across the file, so the same construction used in two zones becomes one record. List them at the top level of the file; a surface simply refers to one by its code.

FieldTypeRequiredDescription
idtextUnique within the file. What constructie_id on a surface refers to. Any readable string will do — Label-wise only uses it to resolve the links inside this file.
codetextThe BCRG code of the quality declaration. Real data, stored on the construction — not a key, and it does not have to be unique.
naamtextDisplay name.
bouwdeeltypeenum ConstructionTypeFACADE · ROOF_SLOPED · ROOF_FLAT · ROOF_FLAT_SLOPED · FLOOR · WINDOW · DOOR · PANEL_IN_FRAME.
rc_waardenumberThermal resistance in m²·K/W. For opaque parts. ¹
u_waardenumberThermal transmittance in W/m²·K. For windows and doors. ¹
g_waardenumberSolar factor (ZTA), for glazing.
invoermethodeenum ConstructionInputTypeDECISION_TREE when the quality follows from building characteristics instead of a measured value.

¹ At least one of rc_waarde or u_waarde is required, unless invoermethode is DECISION_TREE. Label-wise then derives the value from the characteristics below, and an empty Rc/U is correct:

FieldTypeDescription
bouwjaarenum ConstructionBuildingYearConstruction year bracket of the building part.
isolatie_aanwezigenum InsulationConstructionTypeInsulation present or not.
isolatiediktenumberInsulation thickness in mm.
isolatiedikte_onbekendbooleanThickness unknown.
spouw_aanwezigbooleanCavity present.
glasenum GlassTypeGlazing type.
kozijnenum FrameTypeFrame type.
rieten_dakbooleanThatched roof.
rietdikteenum ReedThicknessThatch thickness.

This applies to every bouwdeeltype, not just windows: bouwjaar, isolatie_aanwezig, isolatiedikte and spouw_aanwezig are facade and roof characteristics. So each construction is supplied in one of two ways — a measured value, or the characteristics it follows from:

{ "id": "ramen-voor", "naam": "Ramen voorgevel", "bouwdeeltype": "WINDOW",
  "u_waarde": 1.4, "g_waarde": 0.6 }

{ "id": "gevel-spouw", "naam": "Spouwmuur, isolatie onbekend", "bouwdeeltype": "FACADE",
  "invoermethode": "DECISION_TREE", "bouwjaar": "FROM_1965_UNTIL_1975",
  "spouw_aanwezig": true, "isolatiedikte_onbekend": true }

{ "id": "ramen-achter", "naam": "Ramen achtergevel", "bouwdeeltype": "WINDOW",
  "invoermethode": "DECISION_TREE", "glas": "DOUBLE_GLASS", "kozijn": "WOOD", "g_waarde": 0.7 }

Three other input methods derive the value themselves as well, and leave Rc/U empty for the same reason: U_FRAME_U_GLASS_PSI_GLASS, U_FRAME_U_GLASS_PSI_GLAS_PERIMETER_GLASS_A_WINDOW_A_FRAME and ROOF_DOME.

hoofdvlakken[] — main surfaces

FieldTypeRequiredDescription
idtextUnique within the file. Your reference in the import log, and the target of rbw_gevel_vlak_id and of a dossier item.
naamtextDisplay name.
bouwdeeltypeenum ConstructionTypeSame values as on a construction. Must match the construction it points at.
bruto_oppervlakte_m2numberGross: the surface as you measured it, sub-surfaces included.
netto_oppervlakte_m2numberNet: that same surface minus its sub-surfaces. This is what the calculation uses.
grenst_aanenum BorderTypeWhat is on the other side: OUTSIDE, GROUND, CRAWL_SPACE, UNHEATED_ZONE, …
orientatieenum OrientationTypeCompass direction, e.g. NORTH(0), SOUTH_EAST(135). ¹
locatieenum MainSurfaceLocationFRONT_FACADE, REAR_FACADE, LEFT_FACADE, RIGHT_FACADE, ROOFS, FLOORS.
constructie_idtextRefers to an id in constructies[] — at the top level or in this zone. Empty means the advisor picks one after the import.
breedte_m · hoogte_of_lengte_mnumberDimensions.
hellingshoek_gradennumberSloped roofs only. ¹
dakfactornumber1/cos(angle). Leave it out and Label-wise derives it from hellingshoek_graden.
vormtextrechthoek · driehoek · trapezium. Default rechthoek.
meetwijzetexthorizontaal · schuin. How the surface was measured. Leave it out when you do not know — Label-wise then treats it as horizontaal. Do not guess: on a sloped roof schuin means the engine calculates with the length along the slope, horizontaal with the projection plus the roof factor, and those give different results.
rbw_gevel_vlak_idtextFloors bordering a crawl space only: the id of the adjoining facade in the same zone, for the NTA 8800 Rbw calculation (perimeter insulation).
notitiestextFree text, ends up as remarks on the surface.
deelvlakkenlistWindows, doors and panels within this surface — see below.

¹ Orientation and slope are only meaningful for a facade or a sloped roof. A floor and a flat roof lie horizontally and have no orientation — leave the field out there. A value supplied anyway is ignored, and the import says so.

Both areas are yours to supply. Gross is the surface as you measured it, sub-surfaces included. Net is that same surface minus the sub-surfaces cut out of it. Label-wise stores both and calculates with the net figure — it does not derive one from the other, so make sure they agree with the sub-surfaces you list.

The south facade in the example is 8 × 5.4 = 43.2 m² gross. The 6 m² window comes out of it, leaving 37.2 m² net. breedte_m and hoogte_of_lengte_m keep describing the whole facade.

deelvlakken[] — sub-surfaces

FieldTypeRequiredDescription
idtextUnique within the file.
naamtextDisplay name.
typeenum ConstructionTypeWINDOW · DOOR · PANEL_IN_FRAME. Derived from the construction when omitted, so you rarely need it.
oppervlakte_m2numberArea of the sub-surface.
breedte_m · hoogte_mnumberDimensions.
aantalnumberHow many identical copies this sub-surface represents. Left out, it is 1 — four identical windows are either four entries, or one entry with aantal: 4.
constructie_idtextIts own construction — a window has a different U-value than the facade around it.

Orientation and slope are inherited from the main surface; you do not supply them separately.

Photos and documents

An optional dossier block at the top level of the file. Every item is a photo or a document, optionally attached to a specific surface or construction.

"dossier": [
  {
    "naam": "Hoofdvlak | Gevel | Zuid gevel.jpg",
    "type": "PHOTO",
    "categorie": "GEOMETRY",
    "foto_url": "https://…/zuidgevel.jpg",
    "bestand_url": "https://…/zuidgevel.jpg",
    "koppel_aan": "zuid-gevel"
  }
]
FieldTypeRequiredDescription
naamtextFile name as shown in the dossier.
bestand_urlurlPublicly retrievable URL of the file. ¹
foto_urlurlSame, for an image. Supply both for a photo. ¹
typeenum FileTypePHOTO · DOCUMENT · DRAWING · QUALITY_DECLARATION.
categorieenum FileCategoryOBJECT · GEOMETRY · CONSTRUCTIONS · …
omschrijvingtextFree text.
koppel_aantextThe id of a surface, sub-surface or construction, from this same file. Leave it out to attach the item to the object dossier without a specific link.

¹ At least one of the two. An item without a file is skipped.

koppel_aan that points at nothing is left empty rather than guessed — the item still ends up in the object dossier. So check your ids if a photo does not appear where you expect it.

Enum values

Fields marked as an enum only accept the internal Label-wise values. Retrieve the list once and map your own values against it.

Do not hard-code the values from this page. Label-wise occasionally adds a value — rarely, but it happens — and a value that does not exist causes the import to be refused. Reading the list from this endpoint keeps you in step without a release on your side.

GEThttps://app.label-wise.nl/api/1.1/wf/enums_internal_values_external

Parameters

None.

Response

{
  "status": "<outcome of the request>",
  "response": {
    "BorderType": [
      "OUTSIDE",
      "WATER",
      "HEATED_ZONE",
      "/* … 6 more */"
    ],
    "ObjectType": [
      "RESIDENTIAL",
      "UTILITY"
    ],
    "BuildingSubtype": [
      "FREESTANDING",
      "CORNER",
      "IN_BETWEEN",
      "/* … 2 more */"
    ],
    "Buildingtype": [
      "SINGLE_FAMILY",
      "SINGLE_FAMILY_SHARED",
      "HOUSE_IN_APARTMENT",
      "/* … 10 more */"
    ],
    "BuildIntegrationVentilationType": [
      "NOT",
      "MEDIUM",
      "STRONG",
      "/* … 1 more */"
    ],
    "ConstructionBuildingYear": [
      "UNTIL_1965",
      "FROM_1965_UNTIL_1975",
      "FROM_1975_UNTIL_1983",
      "/* … 9 more */"
    ],
    "/* … 24 more */": ""
  }
}

What the import does not create

Installations are never created from a JSON file. Heating, hot water, ventilation, lighting and cooling stay with the EP advisor: they determine the energy label and require the advisor's own assessment on site. The import builds the project, the object, the geometry, the constructions and the dossier — the advisor completes the installations in Label-wise.

Nor are results calculated during the import. The energy label follows once the advisor has completed the intake.

Validation

The file is checked completely before anything is created. When something is wrong, the import reports which field in which record, and writes nothing:

SituationExample message
Not valid JSON"Dit bestand kon niet gelezen worden — het is geen geldig JSON-bestand."
Unknown meta.formaat"Onbekend of ontbrekend meta.formaat — verwacht 'labelwise-geometrie' of 'labelwise-project'."
Required project field missing"Project: 'objecttype' ontbreekt."
Required surface field missing"Rekenzone 1 (Woning) · vlak zuid-gevel: 'oppervlakte_m2' ontbreekt."
Reference to a non-existent construction"Rekenzone 1 (Woning) · vlak zuid-gevel: constructie_code 'X' bestaat niet in deze zone."
Enum value not recognised"Rekenzone 1 (Woning) · vlak zuid-gevel: grenst_aan 'BUITEN' ongeldig."

The advisor sees these messages on screen before confirming, and can correct the fields there. That does not make the file itself correct — fix the cause in your export as well.

Retrieving the dossier

After the advisor has completed the intake you can pull the dossier — the photos and documents — back into your own system. That takes two steps: once you link your integration to the advisor, and after that you can retrieve a dossier per object.

Only once per EP advisor. The advisor receives an e-mail and confirms the link; from then on the user_id you get back stays valid, so store it alongside your own advisor record.

POSThttps://app.label-wise.nl/api/1.1/wf/find_user

Request body

FieldTypeRequiredDescription
emailstringE-mail address the EP advisor uses in Label-wise.
naam_integratie_partnerstringYour integration partner name.

Response

{
  "status": "<string>",
  "response": {
    "user_id": "<label-wise user id of the ep advisor — use this in all subsequent api calls>",
    "confirmation_email_send": false
  }
}

Step 2 — retrieve the dossier

You identify the object by its full address, together with that user_id — the same address you put in the import file.

Use exactly the address you delivered. The search matches the full address of the object, composed from object_adres_straat, _huisnummer, _huisnummertoevoeging, _postcode and _woonplaats as street number, postcode town — house number and addition written together, and the postcode without a space: Haringburgwal 11B, 1141AT Monnickendam.

A postcode written as 1141 AT is a different address as far as the search is concerned, and will find a different object or none at all. If the advisor corrected the address during the intake, look for the corrected one.

GEThttps://app.label-wise.nl/api/1.1/wf/object_dossier

Parameters

NameInRequiredDescription
naam_integratie_partnerqueryyesYour integration partner name. Free text — use the same name consistently.
user_idqueryyesThe user_id of the EP advisor, from Find user.
object_adresqueryyesFull address of the object, exactly as it was delivered in the import file: street, house number with any addition, postcode without a space, and town.

Response

{
  "status": "<string>",
  "response": {
    "user_id": "<unique id of the user associated with the object>",
    "object_name": "<name of the object>",
    "object_dossier": "<url or reference to the object's dossier file>"
  }
}