Skip to content
You don't have a token yet? Contact Sales

Integration

This guide describes the end-to-end workflow for taking a profile that a user designs in the <nu-evolution-editor> and integrating it with your own application and the nuEvolution backend (the Exchange API).

There are two moving parts:

  • The editor (this library) runs in the browser. It is where the end user designs a profile. The library hands your application a profile ID.
  • The Exchange API runs on nuEvolution's servers. Using the profile ID, your backend can read a profile's details, update its basic properties, delete it, and turn one or more profiles into an order.

Everything below hangs off the profile ID returned by the library.

Call the Exchange API from your backend

The Exchange API is authenticated with a secret header token (nuit-exchange-token). Treat it like any server-side secret - make these requests from your backend, never directly from the browser, so the token is not exposed to end users.

The flow at a glance

The sequence below shows the conversation between everyone involved. Note the boundary: the editor runs in the browser, while the Exchange API calls are made from your backend, so the secret token never reaches the browser.

  1. Open the editor - the user designs a profile in <nu-evolution-editor>.
  2. Capture the ID - your page calls saveProfile() (or listens for the nuit::profile-saved event) and receives a profile ID from the library.
  3. Persist the ID - store that ID in your backend, linked to the user/cart/session it belongs to.
  4. Read details - your backend fetches the profile's properties through the GET route (everything except geometry).
  5. Update - change basic properties (name, remark, …) through the PUT route. The profile geometry is not edited through the API; it is changed by reopening the profile in the editor and saving again (see Update the geometry).
  6. Delete - remove a profile through the DELETE route.
  7. Order - once you have one or more saved profiles, submit them as an order through the POST route.

Authentication & environments

All Exchange API requests are authenticated with an API-key header:

HeaderValue
nuit-exchange-tokenYour secret Exchange API token.

Choose the base URL that matches the environment the editor is pointed at via its env attribute:

Editor envBase URL
prod (default)https://api.nu-it.at/exchangeapi
staginghttps://stg-api.nu-it.at/exchangeapi
devhttps://dev-api.nu-it.at/exchangeapi

The endpoint paths below are relative to the chosen base URL.

1. Open the editor and capture the profile ID

Embed the editor and let the user design a profile, then obtain the profile ID. There are two ways to receive it - both return the same ProfileData object:

ts
import type { NuEvolutionEditor } from '@nuitdev/evo-embedded'

const editor = document.querySelector<NuEvolutionEditor>('nu-evolution-editor')!

const { profileId, externalId } = await editor.saveProfile()
// → send profileId (and externalId) to your backend
ts
import { Capability } from '@nuitdev/evo-embedded'

editor.capabilities = [Capability.SAVE_PROFILE] // adds a save button to the toolbar
editor.addEventListener('nuit::profile-saved', (event) => {
    const { profileId, externalId } = event.detail
    // → send profileId (and externalId) to your backend
})

saveProfile() resolves to a ProfileData object:

FieldTypeDescription
profileIdstringThe nuEvolution profile ID. Always present.
externalIdstring | nullYour own external ID for this profile, if one was assigned; otherwise null.

See Working with profiles for the full save/upsert semantics.

2. Persist the ID in your backend

Store the returned ID against whatever entity owns it in your system (a cart line, a saved configuration, an order draft, …). This stored ID is the key you pass to every Exchange API call.

Which ID to send - and the external flag

The profile routes (GET / PUT / DELETE) take the ID as a path parameter, plus an optional external query parameter that tells the API how to interpret that ID. It defaults to false:

The ID you storedPath {id}external
profileData.profileId (nuEvolution ID)that valuefalse (or omit it)
profileData.externalId (your own ID)that valuetrue

TIP

Because external defaults to false, you only need to send it when you stored your own external ID (then pass external=true). The examples below use the nuEvolution profileId, so they omit it.

3. Read profile details - GET

Fetch a profile's properties. The embed variant always omits the geometry field.

GET /exchangeapi/production/embed/profiles/{id}

Parameters

NameInTypeRequiredDescription
idpathstringYesThe profile ID.
externalquerybooleanNo (default false)Set true when id is your own external ID.
bash
curl "https://api.nu-it.at/exchangeapi/production/embed/profiles/12345" \
  -H "nuit-exchange-token: $NUIT_EXCHANGE_TOKEN"

Responses

StatusMeaning
200The profile, as a Profile object.
404No profile with that ID exists.

The Profile object

This is the shape returned by GET and the shape you send back on PUT.

FieldTypeDescription
idintegernuEvolution profile ID.
externalIdstring | nullYour external profile ID.
externalDataobjectFree-form JSON reserved for the external system.
namestringProfile name.
remarkstringProfile remark.
materialIdintegernuEvolution material ID associated with the profile.
materialobjectMaterial object.
lengthnumberProfile length [mm].
quantityintegerProfile quantity. Only populated when the profile is embedded in an order/offer.
blanknumberProfile blank - sum of all segment lengths [mm].
tiltingsCountintegerNumber of tiltings.
hemsCountintegerNumber of hems.
m2numberProfile surface area [m²].
weightnumber | nullProfile weight = blank × length × material.weight [kg].
bendingLengthnumberBending length [mm].
conicalBaseintegerConical base flag/value.
unitstringUnit used for length values (e.g. "mm").
imagestringProfile preview image URL.
punchesobject[]Punch definitions. Contact your nuIT representative for details.
customDataobjectFree-form JSON reserved for customer-specific data.
specialsobject[]Profile specials. Contact your nuIT representative for details.
positionsobject[]Length × quantity variations of the profile (see below).
updatedAtinteger (int64)Last update timestamp (unix seconds).
updatedByintegernuEvolution user ID of the last editor.
positions[] - profile position fields

Each entry in positions[] is a length × quantity variation with its own metadata and pricing:

FieldTypeDescription
idintegerProfile position ID.
externalIdstringExternal profile position ID.
quantityintegerPosition quantity.
lengthnumberPosition length [mm].
weightnumber | nullPosition weight [kg].
weightOverwrittennumber | nullOverridden weight value, if the caller overrode it.
m2numberPosition surface area [m²].
remarkstringPosition remark.
discountnumberPosition discount [%].
pricenumberTotal price for this position = priceForOne × quantity.
priceForOnenumberPrice for one piece of this position.
pricePerUnitnumberPrice per unit of length (typically per meter).
costPriceobjectFree-form cost-price breakdown.
warningsobject[]Validation/processing warnings attached to the position.
customDataobjectFree-form customer-specific data.
externalDataobjectFree-form JSON reserved for the external system.
overrideValuesobjectPer-field overrides applied to this position.
useOriginalPricebooleanWhen true, the original price is used instead of recomputed.
originalPrice(number/object)Original price before any overrides.

4. Update basic properties - PUT

Update a profile's descriptive properties (such as name and remark).

PUT /exchangeapi/production/embed/profiles/{id}

Parameters - identical to GET: id (path, required) and external (query, optional, defaults to false).

Request body - a partial Profile object (fields above). The body is JSON.

Required vs. optional fields

There are no required fields - send only the properties you want to change. The recommended pattern is to GET the profile first, modify the fields you need, then PUT the result back.

  • Commonly updated: name, remark, and your own identifiers/metadata (externalId, externalData, customData).
  • Computed: fields such as blank, m2, weight, tiltingsCount, hemsCount, bendingLength, positions, image, updatedAt and updatedBy are calculated/maintained by nuEvolution; they are returned for display and are recalculated server-side.
bash
curl -X PUT "https://api.nu-it.at/exchangeapi/production/embed/profiles/12345" \
  -H "nuit-exchange-token: $NUIT_EXCHANGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Window sill - left",
        "remark": "Customer approved"
      }'

Responses

StatusMeaning
200Updated profile, returned as a Profile (no geometry).
404No profile with that ID exists.

5. Update the geometry - via the editor

The profile geometry is never updated through the API. To change a profile's geometry, take it back through the library:

  1. Load the existing profile into the editor by setting its profile-id (set id-type="external" if you stored your own external ID).
  2. Let the user edit the geometry.
  3. Call saveProfile() again. Because a profile-id is set, the save is an upsert that updates the same profile - its ID does not change.
ts
import { EditorIdType } from './EditorIdType'

editor.profileId = '12345'
editor.idType = EditorIdType.DEFAULT // or 'EditorIdType.EXTERNAL'
// … user edits the geometry …
await editor.saveProfile()

See Working with profiles → Saving a profile for the upsert details.

6. Delete a profile - DELETE

Remove a profile by ID.

DELETE /exchangeapi/production/embed/profiles/{id}

Parameters - identical to GET: id (path, required) and external (query, optional, defaults to false).

bash
curl -X DELETE "https://api.nu-it.at/exchangeapi/production/embed/profiles/12345" \
  -H "nuit-exchange-token: $NUIT_EXCHANGE_TOKEN"

Responses

StatusMeaning
204Profile deleted (no body).
404No profile with that ID exists.

7. Create an order - POST

Once you have one or more saved profiles, submit them as an order. This endpoint accepts a batch payload - a flat list of profile references with quantity and length.

POST /exchangeapi/shop/embed/orders

Request body - a BatchOrderCreate object. The body itself is required.

FieldTypeRequiredDescription
batchesobjectYesContainer for the order's line items (see below).
externalIdstringOptionalYour external order ID (e.g. the ID from your ERP/shop).
externalDataobjectOptionalFree-form JSON reserved for the external system.
detailsobjectOptionalCart-level details (project name, shipping type, addresses, …). Out of scope for this guide.

batches holds two arrays - profiles[] and products[]. Provide your profile references in batches.profiles[].

batches.profiles[] - profile reference

FieldTypeRequiredDescription
idintegerOne of id / externalIdnuEvolution profile ID.
externalIdstringOne of id / externalIdYour external profile ID.
quantityintegerOptionalQuantity to order. Defaults to 1
lengthnumberOptionalProfile length in mm. If not set, the length set in the embedded editor is used.

Mapping the library ID into a batch

profileData.profileId is the nuEvolution ID returned as a string. To use it as the numeric batches.profiles[].id, convert it (e.g. Number(profileId)), or reference the profile by externalId instead.

bash
curl -X POST "https://api.nu-it.at/exchangeapi/shop/embed/orders" \
  -H "nuit-exchange-token: $NUIT_EXCHANGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "externalId": "ORDER-2026-0001",
        "batches": {
          "profiles": [
            { "id": 12345, "quantity": 2, "length": 1500 },
            { "id": 12346, "quantity": 1, "length": 980 }
          ]
        }
      }'

Responses

StatusMeaning
200Order created, returned as an Order object. Each profile in profiles[] has its geometry omitted.

The response Order object contains the created order (id, number, status, the resolved profiles[], pricing under sales, and so on). Its full shape - together with the details, products, and address structures omitted above - is beyond the scope of this guide; reach out to your nuIT representative if you need those fields.