Quickstart
From a key to finished minutes, in five steps and one language of your choosing.
- 01
Get a key
For an organisation's integration, an administrator creates an integration in NotulAI under Koppelingen and issues a key on it. For your own automation, you create a personal key on your own account page, when your organisation has that enabled; it acts as you and sees what you see. Either way the key is shown once. Store it the way you store a password, and never in a browser or a mobile app.
- 02
Check that it works
Every call goes to
https://api.notulai.nlwith the key in theAuthorizationheader. Listing meetings is the cheapest way to confirm the key, the scope and the network path in one go.curl -X GET 'https://api.notulai.nl/v1/meetings?limit=25' \ -H 'Authorization: Bearer nla_live_...' - 03
Create a meeting
A title and a date are enough. Pass
external_idto carry your own reference: repeating the call with the same value returns the meeting you already made instead of a second one, so a retry after a lost response is harmless.curl -X POST 'https://api.notulai.nl/v1/meetings' \ -H 'Authorization: Bearer nla_live_...' \ -H 'Content-Type: application/json' \ -d '{ "date": "2026-09-01", "external_id": "CRM-4821", "participant_ids": [ "emp_2f1c9a", "emp_7d4b02" ], "project_id": "proj_5b28e4", "shared_with": [ "emp_2f1c9a" ], "template_id": "tpl_9c31a7", "time": "09:30", "title": "Weekly stand-up", "visibility": "organisation" }' - 04
Ask where to put the audio
Name the file's MIME type and you get back an
upload_urlthat is signed for exactly that type, plus how long it stays valid.curl -X POST 'https://api.notulai.nl/v1/meetings/mtg_b39d31c7/upload-url' \ -H 'Authorization: Bearer nla_live_...' \ -H 'Content-Type: application/json' \ -d '{ "content_type": "audio/mpeg" }' - 05
Upload the file
Now PUT the file straight to that URL. This is the one call that does not go to
api.notulai.nl: the audio goes to storage directly, so it never passes through this API. Send no Authorization header, because the signed URL already carries its own, and send the same Content-Type you asked the URL for. The meeting moves toaudio_uploadedby itself.# UPLOAD_URL is the upload_url from the previous response. curl -X PUT "$UPLOAD_URL" \ -H 'Content-Type: audio/mpeg' \ --data-binary '@meeting.mp3' - 06
Wait, then collect
Transcription and minutes run in the background. Poll the meeting until its status is
minutes_ready, then fetch the minutes. Thirty seconds between polls is plenty.curl -X GET 'https://api.notulai.nl/v1/meetings/mtg_b39d31c7' \ -H 'Authorization: Bearer nla_live_...'
Uploading is the one call that leaves the envelope
Content-Type you asked it for. Send a different one and storage rejects the signature with an XML body instead of our error envelope. See from audio to minutes.Where to go next
- Scopes decide what a key may do.
- Errors lists every code you can receive.
- The reference has a sheet per endpoint.