1. Overzicht

Met de 1draad API lees je de laatst opgeslagen versie van de projecten in je account. Elk API-token hoort bij één account en geeft toegang tot alle projecten van dat account, ongeacht welke gebruiker het project aanmaakte.

Basis-URL

Alle endpoints in deze documentatie staan onder:

https://app.1draad.be/api/v1

De API is ook beschikbaar op de Franstalige en Engelstalige domeinen (app.1filaire.be en app.1wire.be). Het domein heeft geen invloed op de gegevens die je terugkrijgt.

Wat v1 niet doet

  • Wijzigingen die nog niet opgeslagen zijn, of die offline in de browser staan, zitten niet in de API.
  • Projecten aanmaken, aanpassen of verwijderen kan niet: de API is alleen-lezen.
  • Tokens beheer je in de app, niet via de API.

OpenAPI-specificatie

Het volledige, machineleesbare contract staat op app.1draad.be/api/v1/openapi.yaml. Je kan het inladen in Postman, Insomnia of een codegenerator om een client te maken.

MCP voor AI-assistenten

Dezelfde gegevens kan je ook via MCP openstellen voor een AI-assistent. Daarvoor meld je je gewoon aan met je account; een API-token is niet nodig.

2. Authenticatie

Een API-token aanmaken

  1. Meld je aan op app.1draad.be.
  2. Open het gebruikersmenu rechtsboven, kies Integraties (onder Gebruikers) en open het tabblad REST API.
  3. Geef het token een herkenbare naam, bijvoorbeeld de naam van je ERP-koppeling, en klik op Token aanmaken.
  4. Kopieer het token meteen. Het volledige token wordt maar één keer getoond.
Bewaar het token als een wachtwoord. Elk token heeft volledige API-toegang tot alle projecten van het account; er zijn geen beperkte rechten per token. Zet het in de geheime instellingen van je integratie, nooit in broncode of in een URL.

Een token hoort bij het account, niet bij de gebruiker die het aanmaakte. Het blijft geldig tot iemand het intrekt of tot het account verwijderd wordt, ook als de gebruiker die het aanmaakte uit het account verdwijnt. Elke gebruiker van het account kan alle tokens zien, aanmaken en intrekken. Op dezelfde pagina zie je per token wanneer het laatst gebruikt werd.

Het token meesturen

Stuur het token bij elk verzoek mee in de Authorization-header:

Shell
curl https://app.1draad.be/api/v1/projects \
  -H "Authorization: Bearer $DENDRAAD_API_TOKEN"
  • Een token in een queryparameter wordt niet aanvaard, en een aangemelde browsersessie geeft geen toegang tot de API.
  • Ontbreekt het token, of is het ongeldig of ingetrokken, dan krijg je 401 met een WWW-Authenticate: Bearer realm="1draad API"-header.
  • Alle antwoorden hebben Cache-Control: no-store.

3. Projecten oplijsten

GET/projects

Geeft alle niet-verwijderde projecten van het account terug, van alle gebruikers, gesorteerd van nieuw naar oud (created_at aflopend, daarna id aflopend).

Queryparameters

ParameterStandaardBetekenis
page1Paginanummer, positief geheel getal.
per_page50Aantal projecten per pagina, van 1 tot en met 100.
queryleegZoekt hoofdletterongevoelig in projectnaam, referentie, klantgegevens, installatieadres en EAN. Wordt afgekapt na 200 tekens.
updated_sincegeenISO 8601-tijdstip, bijvoorbeeld 2026-10-23T09:00:00Z. Geeft enkel projecten die op of na dat moment gewijzigd werden.
Verzoek
curl "https://app.1draad.be/api/v1/projects?per_page=100&query=ERP-101" \
  -H "Authorization: Bearer $DENDRAAD_API_TOKEN"
Antwoord · 200
{
  "data": [
    {
      "id": 123,
      "name": "Plaatsing thuisbatterij",
      "reference": "ERP-101",
      "client_name": "Jan Peeters",
      "installation_ean": "541234567890123456",
      "created_at": "2026-10-23T09:00:00.000000Z",
      "updated_at": "2026-10-23T10:00:00.000000Z",
      "app_url": "https://app.1draad.be/projects/123/edit",
      "share_url": null
    }
  ],
  "pagination": { "page": 1, "per_page": 100, "total_count": 1, "total_pages": 1 }
}

Velden van een project

VeldTypeBetekenis
idintegerVaste projectidentificatie. Gebruik deze om projecten aan je eigen records te koppelen.
namestringProjectnaam.
referencestring | nullJe eigen referentie, bijvoorbeeld een dossier- of ordernummer uit je ERP.
client_namestring | nullNaam van de klant.
installation_eanstring | nullEAN-code van de installatie.
created_at, updated_atdate-timeISO 8601 in UTC, met microseconden. updated_at verandert bij elke opgeslagen wijziging, ook aan het schema.
app_urluriLink om het project in de editor te openen. Werkt alleen voor een aangemelde gebruiker met toegang tot het account.
share_urluri | nullPublieke deellink, alleen als delen al ingeschakeld is. Een API-verzoek schakelt delen nooit zelf in.

De links gebruiken het domein van de exporttaal van het project: app.1draad.be, app.1filaire.be of app.1wire.be.

Paginering

De lijst werkt met genummerde pagina's. Als er tijdens het overlopen projecten bijkomen of verdwijnen, kan een project naar een andere pagina verschuiven en twee keer of helemaal niet opduiken. Ontdubbel daarom altijd op id, en zie Synchroniseren voor een robuuste aanpak.

4. Projectgegevens

GET/projects/{id}

Geeft alle velden uit de lijst terug, aangevuld met de administratieve gegevens van het project en vier contactfiches.

VeldTypeBetekenis
account_idintegerAccount waartoe het project hoort.
owned_by_idinteger | nullGebruiker die eigenaar is van het project.
client_languagestring | nullTaal van de klant: nl, fr of en.
installation_kindstringdomestic (huishoudelijk) of non_domestic (niet-huishoudelijk).
installation_same_as_clientbooleanHet installatieadres is hetzelfde als het adres van de klant.
current_typestring | nullStroomtype zoals ingevuld, vrije tekst, bijvoorbeeld 3 x 400V + N ~ 50Hz.
clientContactKlant.
installation_locationContactPlaats van de installatie.
installerContactInstallateur.
controllerContactKeuringsorganisme.

Elke contactfiche heeft dezelfde velden: name, street, postal_code, city, country, company_number, fixed_phone, mobile_phone en email. Wat niet ingevuld is, blijft null of leeg.

Installatieadres: als installation_same_as_client true is, gebruik je de gegevens uit client als installatieadres. installation_location bevat dan enkel wat er apart opgeslagen is, en kan leeg of verouderd zijn.
Antwoord · 200 (verkort)
{
  "data": {
    "id": 123,
    "name": "Plaatsing thuisbatterij",
    "reference": "ERP-101",
    "client_name": "Jan Peeters",
    "installation_ean": "541234567890123456",
    "created_at": "2026-10-23T09:00:00.000000Z",
    "updated_at": "2026-10-23T10:00:00.000000Z",
    "app_url": "https://app.1draad.be/projects/123/edit",
    "share_url": null,
    "account_id": 7,
    "owned_by_id": 15,
    "client_language": "nl",
    "installation_kind": "domestic",
    "installation_same_as_client": true,
    "current_type": "3 x 400V + N ~ 50Hz",
    "client": {
      "name": "Jan Peeters",
      "street": "Stationsstraat 12",
      "postal_code": "3000",
      "city": "Leuven",
      "country": "België",
      "company_number": null,
      "fixed_phone": null,
      "mobile_phone": "0470 12 34 56",
      "email": "[email protected]"
    },
    "installation_location": { "name": null, "street": null, ... },
    "installer": { ... },
    "controller": { ... }
  }
}

5. Eendraadschema uitlezen

GET/projects/{id}/schematic

Geeft een leesbare weergave van de opgeslagen schema's: alle componenten met hun instellingen, de kring waarin ze zitten en de notities. Het antwoord komt uit één opgeslagen versie van het project en verandert niets aan het project.

Antwoord · 200 (verkort)
{
  "data": {
    "project_id": 123,
    "updated_at": "2026-10-23T10:00:00.000000Z",
    "property_units": { "amperage": "A", "delta_current": "mA", "cross_section": "mm²", "length": "m" },
    "schematics": [
      {
        "id": "schema-1",
        "name": "Schema 1",
        "root_component_ids": ["board-789"],
        "components": [ ... ],
        "annotations": [
          { "id": "note-1", "anchor_component_id": "battery-123", "text": "Geplaatst in de garage" }
        ],
        "backup_connections": [
          { "id": "backup-1", "converter_component_id": "converter-456", "switchboard_component_id": "board-789" }
        ]
      }
    ]
  }
}

Schema's

Een project kan meerdere schema's bevatten. Elk schema in schematics heeft:

VeldBetekenis
id, nameIdentificatie en naam van het schema.
root_component_idsDe componenten bovenaan de boom, in volgorde.
componentsAlle componenten van het schema (zie hieronder).
annotationsNotities met id, anchor_component_id en text. Een losse tekst heeft anchor_component_id: null; tekst die toevallig dicht bij een component staat, wordt niet als gekoppeld beschouwd.
backup_connectionsNoodstroomverbindingen tussen een omvormer (converter_component_id) en een noodstroombord (switchboard_component_id).

Componenten

Voorbeeld van een component
{
  "id": "battery-123",
  "type": "battery",
  "label": "Battery",
  "description": "Merk: Voorbeeld\nS/N: BAT-001",
  "properties": { "quantity": 1, "label": "B1" },
  "parent_id": "converter-456",
  "child_ids": [],
  "connection": {},
  "switchboard_id": "board-789",
  "circuit_id": "breaker-234",
  "circuit_label": "B",
  "circuit_name": "Kring thuisbatterij",
  "phase": "L1",
  "subcircuit_id": "battery-123",
  "subcircuit_label": 1,
  "subcircuit_name": null
}
VeldBetekenis
idIdentificatie van de component binnen het project.
typeVast componenttype uit de editor, bijvoorbeeld battery of switchboard. Gebruik dit veld in je code.
labelLeesbare, Engelstalige naam van het type. Bedoeld voor weergave, niet om op te filteren.
descriptionDe omschrijving exact zoals ingetypt, of null.
propertiesOpgeslagen instellingen met snake_case-sleutels: varianten, elektrische waarden, aantal, … Een tekstcomponent bewaart zijn tekst in properties.content.
parent_id, child_idsPlaats in de boom van het schema. De volgorde van child_ids is de volgorde van de aftakkingen.
connectionOpgeslagen poorten van omvormers en bedieningen, en zijde en positie van aftakkingen en noodstroomborden. Een leeg object betekent dat er niets opgeslagen is.
switchboard_idHet dichtstbijzijnde bovenliggende verdeelbord.
circuit_id, circuit_label, circuit_nameDe kring: verwijzing naar de component die de kring bepaalt, de letter op de tekening en de kringnaam.
phaseDe fase van de kring, bijvoorbeeld L1.
subcircuit_id, subcircuit_label, subcircuit_nameDe subkring, op dezelfde manier. Het label is meestal een getal.
Geen interpretatie. De API geeft enkel terug wat er opgeslagen is. Merken, serienummers of capaciteiten worden niet uit de omschrijving gehaald, er worden geen standaardwaarden van de editor ingevuld en er wordt niets gekoppeld aan artikels in je ERP. In oudere projecten kunnen de kringvelden ontbreken; die zijn dan null.

Eenheden

property_units vertelt in welke eenheid bekende instellingen staan:

InstellingEenheid
amperageA
delta_currentmA (differentieelstroom)
cross_sectionmm² (kabeldoorsnede)
lengthm

Identiteit en consistentie

Een component is uniek binnen de combinatie (project_id, schematic_id, component_id). Haal je projectgegevens en schema in aparte verzoeken op, vergelijk dan updated_at om zeker te zijn dat ze bij dezelfde opgeslagen versie horen.

6. Synchroniseren

Om je eigen systeem bij te werken, vraag je periodiek de projecten op die sinds de vorige keer gewijzigd zijn:

  1. Noteer het tijdstip voor je begint.
  2. Overloop alle pagina's van GET /projects?updated_since=… met het tijdstip van de vorige run, en ontdubbel op id.
  3. Haal voor elk gewijzigd project de gegevens of het schema op als je die nodig hebt.
  4. Bewaar het tijdstip uit stap 1 als startpunt voor de volgende run. Omdat updated_since inclusief is, mis je zo niets; een project dat twee keer binnenkomt, overschrijf je gewoon.
JavaScript (Node.js 18+)
const BASE_URL = "https://app.1draad.be/api/v1";
const headers = { Authorization: `Bearer ${process.env.DENDRAAD_API_TOKEN}` };

// Alle projecten die op of na `since` gewijzigd zijn, ontdubbeld op id.
async function changedProjects(since) {
  const projects = new Map();
  for (let page = 1; ; page++) {
    const url = new URL(`${BASE_URL}/projects`);
    url.search = new URLSearchParams({ page, per_page: 100, updated_since: since });
    const response = await fetch(url, { headers });
    const body = await response.json();
    if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);

    body.data.forEach((project) => projects.set(project.id, project));
    if (page >= body.pagination.total_pages) return [...projects.values()];
  }
}
Verwijderde projecten: updated_since geeft geen verwijderde projecten terug. Wil je verwijderingen opvolgen, vergelijk dan af en toe de volledige lijst (zonder updated_since) met je eigen gegevens. Een verwijderd project geeft ook 404 op GET /projects/{id}.

7. MCP voor AI-assistenten

POST/mcp

Dezelfde gegevens zijn ook beschikbaar als MCP-server (Model Context Protocol). Een AI-assistent die MCP ondersteunt, zoals Claude of ChatGPT, kan dan zelf je projecten opzoeken en schema's lezen, bijvoorbeeld om een materiaallijst op te stellen of een vraag over een installatie te beantwoorden.

https://app.1draad.be/mcp

De server gebruikt het transport Streamable HTTP en staat ook op app.1filaire.be en app.1wire.be. Je verbindt op twee manieren: door je aan te melden met je 1draad-account (aanbevolen), of met een API-token.

Verbinden door aan te melden (aanbevolen)

Hiervoor heb je geen token nodig. Je meldt je aan en keurt elke AI-client zelf goed.

  1. Voeg de URL hierboven toe als externe MCP-server (Streamable HTTP) in je AI-client. Kies OAuth als de client vraagt hoe hij moet aanmelden.
  2. Meld je aan met je bestaande 1draad-account wanneer de client erom vraagt.
  3. Controleer het account en het terugkeeradres, en klik op Alleen-lezen toegang toestaan. De client verschijnt dan onder Integraties → AI-assistenten (MCP) → Verbonden AI-clients.
Claude Code
claude mcp add --transport http 1draad https://app.1draad.be/mcp
# Daarna in Claude Code: /mcp, kies 1draad en meld je aan.
Codex (OpenAI)
codex mcp add 1draad --url https://app.1draad.be/mcp
codex mcp login 1draad
# Opent je browser om aan te melden.

ChatGPT: zet in de instellingen onder Apps → Advanced settings de Developer mode aan. Kies daarna Apps → Create, vul de MCP-URL in, kies OAuth als authenticatie en meld je aan. Of en waar dit kan, hangt af van je ChatGPT-abonnement; in een werkruimte moet een beheerder het soms eerst toestaan.

  • De client kan alle opgeslagen projecten, contactgegevens en schema's van het account lezen. Projecten wijzigen of delen inschakelen kan hij niet.
  • Je moet elke verbinding zelf goedkeuren, ook als dezelfde client al eerder verbonden was. De naam van de client komt van de client zelf en is niet geverifieerd: keur alleen goed als je de verbinding zelf gestart hebt.
  • Elke gebruiker van het account kan een verbinding intrekken via Verbinding intrekken. De client verliest dan meteen de toegang; andere verbindingen en API-tokens blijven werken.
  • Een verbinding hoort bij de gebruiker die ze goedkeurde. Verdwijnt die gebruiker uit het account, dan vervalt ook de verbinding. Na 90 dagen vervalt ze altijd en verbind je opnieuw.
  • De aanmelding geldt per domein: een verbinding via app.1draad.be werkt niet op app.1filaire.be of app.1wire.be, en ze geeft geen toegang tot de REST-API.

Verbinden met een API-token

Kan je client niet aanmelden, maar ondersteunt hij een eigen Authorization-header? Stuur dan een API-token mee als Bearer-token, zoals bij de REST-API (zie Authenticatie).

mcp.json (bijvoorbeeld Cursor)
{
  "mcpServers": {
    "1draad": {
      "url": "https://app.1draad.be/mcp",
      "headers": { "Authorization": "Bearer JOUW_API_TOKEN" }
    }
  }
}
Tip: maak voor je AI-assistent een apart token aan, bijvoorbeeld met de naam "AI-assistent". Trek je het in, dan verliest de assistent meteen de toegang, zonder dat je andere koppelingen stilvallen.

Tools

Alle tools zijn alleen-lezen en geven hetzelfde JSON-antwoord als de overeenkomstige REST-endpoint.

ToolArgumentenKomt overeen met
list_projectsOptioneel: page, per_page, query, updated_since, met dezelfde betekenis als bij de REST-API.GET /projects
get_projectVerplicht: project_id (geheel getal).GET /projects/{id}
get_project_schematicVerplicht: project_id (geheel getal).GET /projects/{id}/schematic

Het resultaat staat zowel in structuredContent als als JSON-tekst in content, zodat ook clients zonder ondersteuning voor gestructureerde resultaten het kunnen lezen. Omschrijvingen en notities in een project zijn gegevens van de gebruiker; de server vraagt AI-clients om ze niet als instructies te behandelen.

Fouten

  • Een onbekend, verwijderd of ander project, of een ongeldig argument, geeft een toolresultaat met isError: true en hetzelfde error-object als de REST-API (not_found of invalid_parameters).
  • Een onbekende tool of methode geeft een JSON-RPC-protocolfout.
  • Zonder geldig API-token of OAuth-toegangstoken krijg je HTTP 401, met een WWW-Authenticate-header die naar de OAuth-gegevens van de server verwijst.

Technische details

Dit heb je enkel nodig als je zelf een MCP-client bouwt.

Transport

  • Ondersteunt MCP-protocolversie 2025-11-25 en de eerdere versies van de officiële MCP Ruby SDK. Stuur eerst initialize, dan notifications/initialized, en geef daarna de onderhandelde versie mee in de header MCP-Protocol-Version. Een niet-ondersteunde versie geeft HTTP 400.
  • Elke POST heeft Content-Type: application/json en Accept: application/json, text/event-stream. Antwoorden zijn JSON; een notificatie krijgt een leeg antwoord met HTTP 202.
  • De server is stateless: geen sessie-ID, geen blijvende SSE-stream. GET en DELETE geven HTTP 405.
  • Native clients zonder Origin-header zijn welkom. Met een Origin-header worden alleen de drie app-domeinen aanvaard; andere geven HTTP 403. Rechtstreeks vanuit een webpagina op een ander domein (CORS) werkt dus niet.

OAuth

EndpointDoel
GET /.well-known/oauth-protected-resource/mcpGegevens van de MCP-resource en de autorisatieserver.
GET /.well-known/oauth-authorization-serverMetadata van de autorisatieserver.
POST /oauth/registerDynamische clientregistratie (RFC 7591).
GET /oauth/authorizeAanmelden en toestemming geven.
POST /oauth/tokenCode inwisselen en tokens vernieuwen.
POST /oauth/revokeVerbinding intrekken.
  • Enkel de authorization-code-flow met PKCE (S256), verplicht voor elke client. De enige scope is mcp:read.
  • Registreer je client met client_name, exacte redirect_uris en token_endpoint_auth_method (none, client_secret_basic of client_secret_post). Terugkeeradressen moeten HTTPS gebruiken, behalve HTTP op een loopback-adres voor native clients. Client ID Metadata Documents worden nog niet ondersteund.
  • Geef de MCP-URL mee als resource-parameter, bijvoorbeeld https://app.1draad.be/mcp. Tokenverzoeken gebruiken application/x-www-form-urlencoded.
  • Een toegangstoken is één uur geldig. Bij elke vernieuwing krijg je een nieuw toegangs- én vernieuwingstoken; bewaar beide en vernieuw nooit twee keer tegelijk. Een oud vernieuwingstoken opnieuw gebruiken trekt de hele verbinding in.
Een tool aanroepen met curl
curl https://app.1draad.be/mcp \
  -H "Authorization: Bearer $DENDRAAD_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  --data '{"jsonrpc":"2.0","id":2,"method":"tools/call",
           "params":{"name":"list_projects","arguments":{"query":"ERP-101","per_page":10}}}'

8. Foutmeldingen

Bij een fout krijg je een JSON-object met een vaste code en een Engelstalige message. Baseer je logica op de code, niet op de tekst.

Antwoord · 404
{ "error": { "code": "not_found", "message": "Project not found." } }
StatusCodeWanneer
400invalid_parametersOngeldige page of per_page, of een updated_since dat geen ISO 8601-tijdstip is.
401unauthorizedToken ontbreekt, is ongeldig of is ingetrokken.
404not_foundHet project bestaat niet, is verwijderd of hoort bij een ander account. Om veiligheidsredenen zegt de API niet welke van de drie.

9. Versies en compatibiliteit

Wijzigingen die bestaande integraties kunnen breken, komen in een nieuwe namespace (/api/v2). Binnen v1 kunnen er wel dingen bijkomen. Schrijf je integratie zo dat ze die verdraagt:

  • nieuwe velden in een antwoord,
  • nieuwe componenttypes in type,
  • nieuwe instellingen in properties en connection.

Vragen over de API, of een gegeven dat je mist voor je koppeling? Laat het ons weten via het contactformulier.