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
- Meld je aan op app.1draad.be.
- Open het gebruikersmenu rechtsboven, kies Integraties (onder Gebruikers) en open het tabblad REST API.
- Geef het token een herkenbare naam, bijvoorbeeld de naam van je ERP-koppeling, en klik op Token aanmaken.
- Kopieer het token meteen. Het volledige token wordt maar één keer getoond.
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:
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
401met eenWWW-Authenticate: Bearer realm="1draad API"-header. - Alle antwoorden hebben
Cache-Control: no-store.
3. Projecten oplijsten
Geeft alle niet-verwijderde projecten van het account terug, van alle gebruikers, gesorteerd van nieuw naar oud
(created_at aflopend, daarna id aflopend).
Queryparameters
| Parameter | Standaard | Betekenis |
|---|---|---|
page | 1 | Paginanummer, positief geheel getal. |
per_page | 50 | Aantal projecten per pagina, van 1 tot en met 100. |
query | leeg | Zoekt hoofdletterongevoelig in projectnaam, referentie, klantgegevens, installatieadres en EAN. Wordt afgekapt na 200 tekens. |
updated_since | geen | ISO 8601-tijdstip, bijvoorbeeld
2026-10-23T09:00:00Z. Geeft enkel projecten die op of na dat moment gewijzigd werden. |
curl "https://app.1draad.be/api/v1/projects?per_page=100&query=ERP-101" \
-H "Authorization: Bearer $DENDRAAD_API_TOKEN"
{
"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
| Veld | Type | Betekenis |
|---|---|---|
id | integer | Vaste projectidentificatie. Gebruik deze om projecten aan je eigen records te koppelen. |
name | string | Projectnaam. |
reference | string | null | Je eigen referentie, bijvoorbeeld een dossier- of ordernummer uit je ERP. |
client_name | string | null | Naam van de klant. |
installation_ean | string | null | EAN-code van de installatie. |
created_at, updated_at | date-time | ISO 8601 in
UTC, met microseconden. updated_at verandert bij elke opgeslagen wijziging, ook aan het
schema. |
app_url | uri | Link om het project in de editor te openen. Werkt alleen voor een aangemelde gebruiker met toegang tot het account. |
share_url | uri | null | Publieke 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
Geeft alle velden uit de lijst terug, aangevuld met de administratieve gegevens van het project en vier contactfiches.
| Veld | Type | Betekenis |
|---|---|---|
account_id | integer | Account waartoe het project hoort. |
owned_by_id | integer | null | Gebruiker die eigenaar is van het project. |
client_language | string | null | Taal van de klant:
nl, fr of en. |
installation_kind | string | domestic
(huishoudelijk) of non_domestic (niet-huishoudelijk). |
installation_same_as_client | boolean | Het installatieadres is hetzelfde als het adres van de klant. |
current_type | string | null | Stroomtype zoals ingevuld, vrije
tekst, bijvoorbeeld 3 x 400V + N ~ 50Hz. |
client | Contact | Klant. |
installation_location | Contact | Plaats van de installatie. |
installer | Contact | Installateur. |
controller | Contact | Keuringsorganisme. |
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.
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.
{
"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": "jan.peeters@example.com"
},
"installation_location": { "name": null, "street": null, ... },
"installer": { ... },
"controller": { ... }
}
}
5. Eendraadschema uitlezen
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.
{
"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:
| Veld | Betekenis |
|---|---|
id, name | Identificatie en naam van het schema. |
root_component_ids | De componenten bovenaan de boom, in volgorde. |
components | Alle componenten van het schema (zie hieronder). |
annotations | Notities 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_connections | Noodstroomverbindingen tussen een omvormer
(converter_component_id) en een noodstroombord (switchboard_component_id). |
Componenten
{
"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
}
| Veld | Betekenis |
|---|---|
id | Identificatie van de component binnen het project. |
type | Vast componenttype uit de editor, bijvoorbeeld battery of
switchboard. Gebruik dit veld in je code. |
label | Leesbare, Engelstalige naam van het type. Bedoeld voor weergave, niet om op te filteren. |
description | De omschrijving exact zoals ingetypt, of null. |
properties | Opgeslagen instellingen met snake_case-sleutels: varianten, elektrische
waarden, aantal, … Een tekstcomponent bewaart zijn tekst in properties.content. |
parent_id, child_ids | Plaats in de boom van het schema. De volgorde
van child_ids is de volgorde van de aftakkingen. |
connection | Opgeslagen poorten van omvormers en bedieningen, en zijde en positie van aftakkingen en noodstroomborden. Een leeg object betekent dat er niets opgeslagen is. |
switchboard_id | Het dichtstbijzijnde bovenliggende verdeelbord. |
circuit_id, circuit_label, circuit_name | De kring: verwijzing naar de component die de kring bepaalt, de letter op de tekening en de kringnaam. |
phase | De fase van de kring, bijvoorbeeld L1. |
subcircuit_id, subcircuit_label, subcircuit_name | De subkring, op dezelfde manier. Het label is meestal een getal. |
null.
Eenheden
property_units vertelt in welke eenheid bekende instellingen staan:
| Instelling | Eenheid |
|---|---|
amperage | A |
delta_current | mA (differentieelstroom) |
cross_section | mm² (kabeldoorsnede) |
length | m |
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:
- Noteer het tijdstip voor je begint.
- Overloop alle pagina's van
GET /projects?updated_since=…met het tijdstip van de vorige run, en ontdubbel opid. - Haal voor elk gewijzigd project de gegevens of het schema op als je die nodig hebt.
- Bewaar het tijdstip uit stap 1 als startpunt voor de volgende run. Omdat
updated_sinceinclusief is, mis je zo niets; een project dat twee keer binnenkomt, overschrijf je gewoon.
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()];
}
}
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
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.
- 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.
- Meld je aan met je bestaande 1draad-account wanneer de client erom vraagt.
- 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 mcp add --transport http 1draad https://app.1draad.be/mcp
# Daarna in Claude Code: /mcp, kies 1draad en meld je aan.
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.bewerkt niet opapp.1filaire.beofapp.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).
{
"mcpServers": {
"1draad": {
"url": "https://app.1draad.be/mcp",
"headers": { "Authorization": "Bearer JOUW_API_TOKEN" }
}
}
}
Tools
Alle tools zijn alleen-lezen en geven hetzelfde JSON-antwoord als de overeenkomstige REST-endpoint.
| Tool | Argumenten | Komt overeen met |
|---|---|---|
list_projects | Optioneel: page, per_page,
query, updated_since, met dezelfde betekenis als bij de REST-API. | GET /projects |
get_project | Verplicht: project_id (geheel getal). | GET /projects/{id} |
get_project_schematic | Verplicht: 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: trueen hetzelfdeerror-object als de REST-API (not_foundofinvalid_parameters). - Een onbekende tool of methode geeft een JSON-RPC-protocolfout.
- Zonder geldig API-token of OAuth-toegangstoken krijg je HTTP
401, met eenWWW-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-25en de eerdere versies van de officiële MCP Ruby SDK. Stuur eerstinitialize, dannotifications/initialized, en geef daarna de onderhandelde versie mee in de headerMCP-Protocol-Version. Een niet-ondersteunde versie geeft HTTP400. - Elke POST heeft
Content-Type: application/jsonenAccept: application/json, text/event-stream. Antwoorden zijn JSON; een notificatie krijgt een leeg antwoord met HTTP202. - De server is stateless: geen sessie-ID, geen blijvende SSE-stream.
GETenDELETEgeven HTTP405. - Native clients zonder
Origin-header zijn welkom. Met eenOrigin-header worden alleen de drie app-domeinen aanvaard; andere geven HTTP403. Rechtstreeks vanuit een webpagina op een ander domein (CORS) werkt dus niet.
OAuth
| Endpoint | Doel |
|---|---|
GET /.well-known/oauth-protected-resource/mcp | Gegevens van de MCP-resource en de autorisatieserver. |
GET /.well-known/oauth-authorization-server | Metadata van de autorisatieserver. |
POST /oauth/register | Dynamische clientregistratie (RFC 7591). |
GET /oauth/authorize | Aanmelden en toestemming geven. |
POST /oauth/token | Code inwisselen en tokens vernieuwen. |
POST /oauth/revoke | Verbinding 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, exacteredirect_urisentoken_endpoint_auth_method(none,client_secret_basicofclient_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, bijvoorbeeldhttps://app.1draad.be/mcp. Tokenverzoeken gebruikenapplication/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.
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.
{ "error": { "code": "not_found", "message": "Project not found." } }
| Status | Code | Wanneer |
|---|---|---|
400 | invalid_parameters | Ongeldige page of
per_page, of een updated_since dat geen ISO 8601-tijdstip is. |
401 | unauthorized | Token ontbreekt, is ongeldig of is ingetrokken. |
404 | not_found | Het 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
propertiesenconnection.
Vragen over de API, of een gegeven dat je mist voor je koppeling? Laat het ons weten via het contactformulier.