Outlook-plugin endpoints
Volledige API-surface voor de Outlook-plugin: zowel de OAuth/sessie-endpoints (publiek bereikbaar) als de plugin-API (JWT-beschermd). Voor de achterliggende architectuur, zie Explanation: Outlook-plugin.
OAuth- en sessie-endpoints
Onder /exact/outlook/*. Bereikbaar zonder backend-auth; bescherming via forceOutlookTenant-middleware of publicRateLimit().
| Methode | Pad | Auth | Doel |
|---|---|---|---|
| GET | /exact/outlook/auth-url |
forceOutlookTenant |
Geeft de Exact OAuth-URL terug die de plugin in een Office-dialog opent. State: <tenantUuid>:outlook[:base64url(email)]. |
| GET | /exact/callback |
publiek | OAuth-callback waar Exact naar terugredirect na inloggen. Wisselt code in voor tokens, upsert in OutlookExactToken, issue plugin-JWT, geeft die als postMessage aan de Office-dialog. |
| POST | /exact/outlook/session/refresh |
JWT (recovery-grace) + publicRateLimit() |
Levert een vers JWT zolang het oude JWT signed is en server-side de koppeling niet revoked is. Accepteert tot 60 dagen verlopen JWTs. |
| POST | /exact/outlook/session/recover |
publiek + rate-limit | Email-based recovery: krijgt { email } in body, geeft een vers JWT als er server-side een geldige OutlookExactToken op die mailbox bekend is. |
| POST | /exact/outlook/session/revoke |
JWT (mag verlopen) + rate-limit | Markeert het OutlookExactToken-doc als revoked. Idempotent — ook zonder geldig JWT antwoordt 200. |
Request/response shapes
POST /exact/outlook/session/refresh
Authorization: Bearer <oude-jwt>
Body: {}
200 OK:
{ "success": true, "data": { "jwt": "<nieuwe-jwt>", "expiresAt": <ms-epoch> } }
401:
{ "success": false, "code": "PLUGIN_SESSION_INVALID", "message": "Plugin sessie verlopen of ongeldig." }
{ "success": false, "code": "EXACT_REAUTH_REQUIRED", "message": "Koppel Exact Online opnieuw." }
POST /exact/outlook/session/recover
Body: { "email": "user@example.com" }
200 OK:
{ "success": true, "data": { "jwt": "<jwt>", "expiresAt": <ms-epoch> } }
400:
{ "success": false, "code": "INVALID_EMAIL", "message": "Ongeldig emailadres." }
401:
{ "success": false, "code": "EXACT_REAUTH_REQUIRED", "message": "Koppel Exact Online opnieuw." }
POST /exact/outlook/session/revoke
Authorization: Bearer <jwt> (optioneel)
Body: {}
200 OK altijd (idempotent):
{ "success": true }
Plugin-API endpoints
Onder /outlook-plugin/*. Beschermd door:
requirePluginSessionmiddleware (verifieert JWT, vist access_token uit vault, zet opreq.pluginSession)exactCallContextMiddleware(zet tenant-context voor logs en error-tracking)publicRateLimit()(per-IP rate-limit)
Elke call verwacht Authorization: Bearer <jwt> in de header.
Plugin-pagina
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/ |
Rendert de plugin-HTML met i18n, CSS-href en JS-href. Cache-Control: no-store. |
Contact-flow
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/contact?email=<email>&outlookItemId=<id> |
Zoekt het Exact-contact bij dit emailadres. Returnt { contact, division, registration, salesLink, excluded, matchedContacts }. |
| GET | /outlook-plugin/contacts/status?emails=<csv> |
Bulk-status voor het Adresboek (heeft contact in Exact ja/nee + excluded ja/nee). |
| GET | /outlook-plugin/contacts/search?q=<query> |
Live-search op naam of email. |
| GET | /outlook-plugin/contacts/:id/details |
Volledige contact-details voor het Adresboek-detailscherm. |
| POST | /outlook-plugin/save |
Maakt of update een contact in Exact. Body via SaveContactBodySchema. |
| POST | /outlook-plugin/contact/exclude |
Markeert een emailadres als “niet relevant voor koppelen”. |
| DELETE | /outlook-plugin/contact/exclude |
Reset de exclude-vlag. |
Organisaties
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/organizations?search=<text> |
Zoek-organisaties op naam (debounced live-search). |
| POST | /outlook-plugin/create-organization |
Quick-create organisatie in Exact (POST Accounts). |
Tijdregistraties
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/work-types |
Lijst van urensoorten. |
| GET | /outlook-plugin/cost-types |
Lijst van kostensoorten. |
| GET | /outlook-plugin/projects?accountId=<id> |
Projecten gekoppeld aan een account. |
| POST | /outlook-plugin/register-time |
Boekt een TimeTransaction in Exact. |
| PUT | /outlook-plugin/update-time |
Update bestaande TimeTransaction. |
| DELETE | /outlook-plugin/delete-time?outlookItemId=<id> |
Verwijdert TimeTransaction. |
CRM / Sales
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/quotations?accountId=<id> |
Offertes gekoppeld aan account. |
| GET | /outlook-plugin/sales-orders?accountId=<id> |
Verkooporders. |
| GET | /outlook-plugin/purchase-orders?accountId=<id> |
Inkooporders. |
| GET | /outlook-plugin/opportunities?accountId=<id> |
Verkoopkansen. |
| GET | /outlook-plugin/opportunity-stages |
Mogelijke stage-waarden. |
| POST | /outlook-plugin/opportunities |
Maakt nieuwe Opportunity aan. |
| PUT | /outlook-plugin/opportunities/:id/stage |
Update Opportunity-stage. |
| POST | /outlook-plugin/activities |
Logt een activiteit (Note of Task) onder een Opportunity. |
| GET | /outlook-plugin/opportunities/:opportunityId/activities |
Lijst activiteiten per Opportunity. |
| PUT | /outlook-plugin/activities/by-id/:activityId |
Update een specifieke activiteit (op type-gebaseerde polymorfe API). |
| DELETE | /outlook-plugin/activities/by-id/:activityId |
Verwijdert een activiteit. |
Archiveren
| Methode | Pad | Doel |
|---|---|---|
| GET | /outlook-plugin/document-types |
Lijst van document-types in Exact (sortable per beschrijving). |
| POST | /outlook-plugin/archive-email |
Archiveert email + bijlagen als Document in Exact. Body bevat emailData (metadata + HTML body) + attachments (base64). Server genereert PDF uit de email, bundelt alle uploads in één Document met automatische rollback bij gedeeltelijke fouten. |
Sessie-uitloggen
| Methode | Pad | Doel |
|---|---|---|
| POST | /outlook-plugin/logout |
Server-side endpoint voor toekomstige session-invalidation. Vandaag is logout client-side (clearSession + revoke + disconnect); dit endpoint blijft voor symmetrie. |
Foutcodes (in response-body)
De plugin-flow gebruikt twee herkenbare error-codes in de 401-body zodat de client-side fetchWithAuth weet wanneer de sessie écht weg moet.
| Code | Wanneer | Client-actie |
|---|---|---|
PLUGIN_SESSION_INVALID |
JWT mist, is gemanipuleerd, of voorbij de recovery-grace | clearSession() + showLoginSection() |
EXACT_REAUTH_REQUIRED |
OutlookExactToken-doc revoked of voorbij de failure-threshold |
clearSession() + showLoginSection() |
INVALID_EMAIL |
Recovery-call zonder of met ongeldig emailadres | client toont login (geen recovery mogelijk) |
Andere 4xx-codes vallen onder generieke error-handling.