Laatst bijgewerkt: 2 oktober 2026
Er zijn drie manieren om met de Layer te werken van buitenaf:
- Een AI-app verbinden via MCP, zoals Claude of ChatGPT. Je logt in bij de Layer en kiest wat de app mag.
- De REST-API voor je eigen software, met een sleutel die je zelf maakt.
- Webhooks: de Layer meldt aan jouw adres dat er iets gebeurde, zoals een betaalde factuur.
1. Zo blijft het veilig
- Nooit meer dan de maker. Een sleutel of verbonden app kan nooit meer dan de persoon die hem maakte. Verandert diens rol, dan verandert de sleutel mee. Gaat iemand uit het team, dan werkt zijn sleutel niet meer.
- Schrijven is altijd een voorstel. Niets van buiten verandert zelf iets in je werkplek. Elke wijziging komt in Goedkeuringen en gebeurt pas als iemand met dat recht hem goedkeurt.
- Tekst van buiten blijft gemarkeerd. Wat via de API of MCP binnenkomt, telt als tekst van buiten. Een voorstel met zulke tekst gaat nooit vanzelf, ook niet als je andere voorstellen wel automatisch laat uitvoeren.
- Zichtbaar en in te trekken. Bij Instellingen, Apparaten zie je elke sleutel en app, wanneer hij voor het laatst werd gebruikt en wat hij deed. Intrekken werkt meteen.
- Een rem. Elke sleutel en app mag 120 verzoeken per minuut doen. Daarboven krijg je een 429 met een Retry-After.
2. Een sleutel maken
In de Layer: Instellingen, Ontwikkelaars, Sleutel voor de API. Geef de sleutel een naam, kies hoe lang hij geldig is (30 dagen, 90 dagen of een jaar) en vink aan wat hij mag. Je ziet de sleutel één keer. Wij bewaren alleen een hash, dus kwijt is kwijt: trek hem in en maak een nieuwe.
Sleutels horen bij je eigen werkplek, niet bij de demo. Het precieze adres van jouw API en MCP-server staat op dezelfde pagina; in de voorbeelden hieronder staat https://jouw-werkplek.example.
| Recht | Wat het geeft |
|---|---|
relaties.lezen | Klanten, leads, leveranciers en hun contactpersonen. |
offertes.lezen | Offertes met hun regels en status. |
facturen.lezen | Facturen met bedragen, status en betaaldatum. |
leads.lezen | Leads met fase, waarde en volgende actie. Met Voorstellen maken ook leads aanmaken en bijwerken. |
communicatie.lezen | De tijdlijn van telefoontjes, mails, gesprekken en notities per relatie. Met Voorstellen maken ook vastleggen. |
mail.lezen | Zoeken en lezen in de postvakken die je in de Layer zelf ziet, met per gesprek wie het laatst schreef en of er al een antwoord is. Alleen lezen, zonder bijlagen. Wat de app leest, gaat naar de AI die je verbindt. |
agenda.lezen | Je eigen afspraken. Met Voorstellen maken ook een afspraak inplannen, zonder uitnodiging. |
facturen.concept | Een conceptfactuur maken (van open uren of met eigen regels) of een open factuur met een link voor de klant, hem aanpassen en de PDF bekijken. Versturen is altijd een voorstel in Goedkeuringen; de link deel je zelf. |
offertes.concept | Een nieuwe offerte als concept. Versturen doe je altijd zelf in de Layer. |
bedrijf.vragen | Zoekt in gespreksverslagen, de kennisbank, klanten, taken en records naar de stukken die bij een vraag passen, met de bron erbij. |
projecten.lezen | Projecten met status, deadline en taken. |
taken.lezen | Taken met status, deadline en prioriteit. |
uren.lezen | Geschreven uren. Bedragen alleen als je rol geld mag zien. |
producten.lezen | Producten en diensten met prijs en voorraad. |
tickets.lezen | Supporttickets met status en prioriteit. |
content.lezen | Posts in de contentkalender met kanaal, datum en status. |
series.lezen | Formats, series en afleveringen met hun stap en oordeel. |
radar.lezen | Ideeën met score en signalen uit de radar: uitschieters, kanaalgroei, zoekvragen. |
social.lezen | Volgers en vaste cijfers per eigen social-account per dag. |
analytics.lezen | Bezoekers en zoekverkeer uit Google Analytics en Search Console. |
radar.sturen | Ontdekken aan of uit zetten, zoektermen en kanalen sturen en de trendanalist starten. Alleen voor wie in de werkplek de radar beheert. |
radar.feedback | Ideeën uit de radar goed of niet goed vinden. Dat stuurt alleen waar de radar zoekt en wat de trendanalist maakt; er gaat niets naar buiten. |
content.voorstellen | Een post als idee in de contentkalender voorstellen. Samen met Voorstellen maken; het wacht in Goedkeuringen. |
verslagen.insturen | Verslagen van TrompTech Notulen in Meetings zetten. Wat ermee gebeurt (taken, contactmoment, mail) kies je daarna zelf. |
verslagen.verwerken | Van een verslag dat je zelf instuurde taken, een contactmoment en een conceptmail maken, zoals de knop Verwerken in Meetings. Alleen wat je rol mag; een mail wordt nooit verstuurd. |
kennis.insturen | Instructievideo's met stappen van TrompTech Uitleg in de kennisbank zetten. |
afletteren.transacties.schrijven | Bijschrijvingen van een rekening in het afletteren zetten, voor een privérekening die ook zakelijk is. Lezen kan met dit recht niet. |
huishouden.lezen | Je huishoudboek (inkomen, vaste lasten, budgetten en schulden), je boodschappenlijst en je taken. Alleen lezen, geen advies. |
huishouden.schrijven | Boodschappen op de lijst zetten, afvinken en weghalen, en huishoudtaken toevoegen en afvinken: direct, met Ongedaan maken. Een schuld of budget blijft altijd een voorstel in Goedkeuringen. Leest ook je huishouden. |
aanbiedingen.lezen | De supermarktaanbiedingen van deze en volgende week uit je aanbiedingen-app, en prijzen per winkel vergelijken voor je boodschappen. Alleen lezen. |
voorstellen.maken | Wijzigingen voorstellen. Ze wachten in Goedkeuringen tot iemand ze goedkeurt; er gebeurt niets vanzelf. |
Een recht werkt alleen als de module in je abonnement zit en je rol het toestaat. Bedragen, zoals een uurtarief, zie je alleen als je rol geld mag zien.
3. De REST-API
Alles staat onder /api/v1. Stuur de sleutel mee als Authorization: Bearer. GET /api/v1 laat zien welke bronnen jouw sleutel kan lezen. De volledige beschrijving staat in /api/v1/openapi.json (OpenAPI 3.1), ook zonder sleutel op te halen.
Lezen en bladeren
curl "https://jouw-werkplek.example/api/v1/taken?status=open&per_pagina=20" \
-H "Authorization: Bearer $LAYER_SLEUTEL"Elke lijst komt in pagina's, nieuwste eerst. Met per_pagina (1 tot 100, standaard 50) en pagina blader je; volgende geeft het adres van de volgende pagina, of null. Filter met status, of met sinds (een datum of tijd in ISO 8601) om alleen op te halen wat sindsdien is gewijzigd.
{
"data": [ { "id": "...", "titel": "...", "status": "open", "deadline": "2026-10-03T07:00:00.000Z" } ],
"pagina": 1,
"per_pagina": 20,
"totaal": 1,
"volgende": null
}| Bron | Recht | Voorstellen |
|---|---|---|
/api/v1/relatiesKlanten, leads en (met de module Leveranciers) leveranciers. | relaties.lezen | nieuw (POST): soort, naam, bedrijf, email, telefoon, adres, postcode, plaats, kvk, btw, branche, notities, bron; wijzigen (PATCH): telefoon, branche, plaats, website, bron |
/api/v1/contactpersonenContactpersonen bij een klant, lead of leverancier. | relaties.lezen | nieuw (POST): naam, bedrijf, email, telefoon, notities, bron |
/api/v1/offertesOffertes met regels, bedrag en status. | offertes.lezen | wijzigen (PATCH): status |
/api/v1/facturenFacturen met regels, bedrag, status en betaaldatum. | facturen.lezen | wijzigen (PATCH): status, betaald_op |
/api/v1/projectenProjecten met status, deadline, taken en voortgang. | projecten.lezen | wijzigen (PATCH): status, deadline |
/api/v1/takenTaken met status, deadline en prioriteit. | taken.lezen | nieuw (POST): titel, omschrijving, deadline, prioriteit, klant_id, project_id; wijzigen (PATCH): status, deadline, prioriteit |
/api/v1/urenGeschreven uren. Tarief en factuur alleen als je rol dat mag zien. | uren.lezen | alleen lezen |
/api/v1/productenProducten en diensten met prijs en voorraad. De inkoopprijs alleen als je rol geld mag zien. | producten.lezen | alleen lezen |
/api/v1/ticketsSupporttickets met status, prioriteit en categorie. | tickets.lezen | wijzigen (PATCH): status |
/api/v1/contentPosts in de contentkalender: datum, kanaal, onderwerp, status en de serie waar ze bij horen. | content.lezen | alleen lezen |
/api/v1/formatsFormats: de vaste opbouw van een aflevering, per platform de vorm en lengte, en de checklist. | series.lezen | alleen lezen |
/api/v1/seriesSeries: een format met cadans, account en status. | series.lezen | alleen lezen |
/api/v1/afleveringenAfleveringen van alle series, met datum, stap, script en oordeel. | series.lezen | alleen lezen |
/api/v1/radar-ideeenIdeeën met score uit de contentradar. De score is een band met onderdelen, nooit een kans op viral. | radar.lezen | alleen lezen |
/api/v1/radar-serievoorstellenSeriesuggesties van de trendanalist: een terugkerende show op een onderwerp dat bij meerdere uitschieters terugkomt. Een serie maken doe je in de Layer zelf. | radar.lezen | alleen lezen |
/api/v1/radar-signalenSignalen van de laatste 90 dagen: uitschieters, vroege uitschieters, kanaalgroei, zoekvragen en nieuws, met de uitleg hoe ze berekend zijn. | radar.lezen | alleen lezen |
/api/v1/social-metingenPer eigen social-account per dag de volgers en de vaste cijfers die het kanaal meldt (laatste 120 dagen). Een ontbrekend cijfer is null, nooit nul. | social.lezen | alleen lezen |
Een wijziging voorstellen
Met het recht voorstellen.maken stel je een nieuw record of een wijziging voor. Het antwoord is een 202: het voorstel staat klaar, er is nog niets veranderd. Geef in waarom mee waarom, dan ziet de beoordelaar dat erbij.
curl -X POST "https://jouw-werkplek.example/api/v1/taken" \
-H "Authorization: Bearer $LAYER_SLEUTEL" \
-H "Content-Type: application/json" \
-d '{"titel": "Offerte nabellen", "deadline": "2026-10-03", "waarom": "Afgesproken in het overleg"}'HTTP/1.1 202 Accepted
{
"voorstel": { "id": "...", "actie": "taak.nieuw", "titel": "...", "status": "wacht", "link": "https://jouw-werkplek.example/app/ai/goedkeuringen?id=..." },
"uitleg": "Dit is een voorstel. Er is nog niets veranderd: het wacht in Goedkeuringen tot iemand het goedkeurt."
}Volg de stand met GET /api/v1/voorstellen of GET /api/v1/voorstellen/{id}; je ziet alleen de voorstellen van je eigen sleutel. Wil je liever een webhook, abonneer je dan op voorstel.goedgekeurd. Andere acties die de AI in de Layer kent, stel je voor met POST /api/v1/voorstellen en {"actie": "...", "gegevens": { ... }}. Kan een actie niet, of mist er iets, dan krijg je een 422 met de reden. Verwijderen kan niet via de API.
Fouten
Een fout is altijd JSON: {"fout": {"code": "...", "melding": "..."}}, met een melding in gewone taal.
| Code | Betekenis |
|---|---|
| 400 | De vraag klopt niet, bijvoorbeeld een ongeldige datum of een ontbrekend veld. |
| 401 | Geen sleutel, of een sleutel die verlopen of ingetrokken is. |
| 403 | De sleutel mist een recht. De kop WWW-Authenticate noemt welk recht. |
| 404 | Dit adres of record bestaat niet, of je mag het niet zien. |
| 405 | Deze methode kan hier niet. De kop Allow noemt wat wel kan. |
| 422 | Het voorstel is geweigerd, met de reden erbij. |
| 429 | Te veel verzoeken. Wacht het aantal seconden uit Retry-After. |
4. Webhooks
Wie in de Layer koppelingen beheert, stelt webhooks in bij Instellingen, Ontwikkelaars, Webhooks: een adres en de gebeurtenissen die je wilt horen. Het geheim om de handtekening te controleren zie je één keer.
| Gebeurtenis | Wanneer |
|---|---|
factuur.verstuurd | Een factuur staat op verstuurd. |
factuur.betaald | Een factuur staat op betaald. |
offerte.geaccepteerd | Een klant ging akkoord met een offerte. |
ticket.nieuw | Er is een supportticket bijgekomen, ook uit een mail. |
taak.afgerond | Iemand rondde een taak af. |
voorstel.goedgekeurd | Een voorstel in Goedkeuringen is goedgekeurd. |
Een bericht is bewust dun: wat er gebeurde en waar je het leest, geen bedragen of klantgegevens. De inhoud haal je op met een sleutel, via href. Het id blijft gelijk als we een bericht opnieuw sturen, dus daarmee herken je een dubbel bericht.
POST /jouw-webhook HTTP/1.1
Content-Type: application/json
TrompTech-Event: factuur.betaald
TrompTech-Delivery: ...
TrompTech-Signature: t=1790931600,v1=...
{
"id": "evt_...",
"type": "factuur.betaald",
"aangemaakt": "2026-10-02T09:00:00.000Z",
"data": { "object": "factuur", "id": "...", "nummer": "...", "href": "/api/v1/facturen/..." }
}De handtekening controleren
De kop TrompTech-Signature bevat een tijd t (in seconden) en v1: een HMAC-SHA256 met je geheim over t, een punt en de body zoals hij binnenkwam. Reken hem zelf na, vergelijk in constante tijd en weiger berichten die ouder zijn dan vijf minuten.
import { createHmac, timingSafeEqual } from "node:crypto";
// geheim: het hele geheim van de webhook, met whsec_ ervoor.
// inhoud: de body precies zoals hij binnenkwam, als tekst (niet eerst als JSON inlezen).
export function handtekeningKlopt(geheim, kop, inhoud) {
const delen = new Map((kop ?? "").split(",").map(d => d.trim().split("=", 2)));
const t = Number(delen.get("t")), v1 = delen.get("v1") ?? "";
// Ouder dan vijf minuten: weigeren, zodat niemand een oud bericht opnieuw kan afspelen.
if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300 || !/^[0-9a-f]{64}$/.test(v1)) return false;
const verwacht = createHmac("sha256", geheim).update(`${t}.${inhoud}`).digest();
return timingSafeEqual(verwacht, Buffer.from(v1, "hex"));
}import hashlib, hmac, re, time
def handtekening_klopt(geheim: str, kop: str, inhoud: bytes) -> bool:
delen = dict(d.strip().split("=", 1) for d in (kop or "").split(",") if "=" in d)
t, v1 = delen.get("t", ""), delen.get("v1", "")
if not t.isdigit() or abs(time.time() - int(t)) > 300 or not re.fullmatch(r"[0-9a-f]{64}", v1):
return False
verwacht = hmac.new(geheim.encode(), t.encode() + b"." + inhoud, hashlib.sha256).hexdigest()
return hmac.compare_digest(verwacht, v1)Bezorgen en opnieuw proberen
- Antwoord binnen 10 seconden met een 2xx. Een doorverwijzing (3xx) volgen we niet.
- Lukt het niet, dan proberen we het opnieuw na 1 minuut, 5 minuten, 30 minuten, 2 uur, 6 uur en 24 uur. Daarna geldt het bericht als mislukt; je kunt het in de Layer opnieuw versturen.
- Mislukken tien berichten achter elkaar, dan gaat de webhook uit. Je zet hem zelf weer aan.
- Alleen https naar een openbaar adres op naam, op de standaardpoort. Een adres dat naar een intern netwerk wijst, krijgt niets; dat controleren we bij elke bezorging opnieuw.
5. Een AI-app verbinden via MCP
De Layer is een MCP-server op https://jouw-werkplek.example/api/mcp (Streamable HTTP). Inloggen gaat met OAuth 2.1 met PKCE: de app stuurt je naar de Layer, je logt in zoals altijd (met je tweede factor als je die hebt) en kiest op het toestemmingsscherm wat de app mag.
- Claude: open Instellingen, Connectors, en voeg een eigen connector toe met het adres van je MCP-server.
- ChatGPT: open Instellingen, Apps en connectors. Zet bij Geavanceerd de ontwikkelaarsmodus aan en maak een connector met het adres, met OAuth als inlog.
- Andere apps: elke MCP-client met OAuth werkt. De Layer ondersteunt dynamische registratie (RFC 7591) en Client ID Metadata Documents, en publiceert zijn gegevens op
/.well-known/oauth-authorization-serveren/.well-known/oauth-protected-resource.
De menunamen in Claude en ChatGPT verschillen soms per versie. De app ziet alleen de tools die bij de gekozen rechten horen. Lezen gaat direct. Ondersteunde protocolversies: 2026-07-28, 2025-11-25, 2025-06-18 en 2025-03-26.
Eerst een plan. Eén losse wijziging doet de app meteen. Meer wijzigingen tegelijk, of iets dat structuur maakt zoals een project met taken, legt hij eerst vast als plan: precies de acties met hun gegevens. Dat plan zie je in je chat, en pas na jouw uitdrukkelijke ja voert de Layer precies die acties uit, één keer. Interne wijzigingen (een lead, contactmoment, notitie, taak, afspraak zonder uitnodiging, project of document) voert de Layer dan meteen uit, als je werkplek dat toestaat. Je ziet ze terug in Goedkeuringen en maakt ze daar ongedaan. Alles wat naar buiten gaat of over geld gaat, zoals een mail, een uitnodiging, een offerte versturen of een factuur, blijft altijd een voorstel dat jij goedkeurt. Een sessie via MCP telt altijd als tekst van buiten.
Een verbonden app blijft werken tot je hem intrekt bij Instellingen, Apparaten, of tot hij 30 dagen niet is gebruikt.
6. Vragen of een probleem gevonden?
Mail info@tromptech.nl. Een beveiligingsprobleem meld je liever vertrouwelijk, zoals beschreven bij Beveiligingsprobleem melden.