Ga naar inhoud

Koppelingen

Eyetelligence is te koppelen aan externe applicaties, zoals bijvoorbeeld Sjapo. Dezelfde gegevens zijn zowel via onze API als via een MCP-server te benaderen. Beide gebruiken dezelfde API-key.

Informatie voor managers

Om te koppelen zul je een API-key moeten aanmaken en deze verstrekken aan de applicatie waarmee je koppelt (bijvoorbeeld Sjapo) zodat ze bij jouw gegevens kunnen. Neem contact met ons op zodat we jouw API-key kunnen verstrekken, dit kun je (nog) niet zelf doen. Dezelfde API-key werkt zowel voor de API als voor de MCP-server.

API

Voor specifiek maatwerk of concullega-applicaties bieden we een GraphQL API aan.

  • We maken gebruik van GraphQL
  • Het schema is beschikbaar op https://cockpit.eyetelligence.nl/api/api/schema
  • Het endpoint is: https://cockpit.eyetelligence.nl/api/api/query
  • De API-key moet als header meegegeven worden in de vorm: Authorization: Bearer [mijn token]
  • Er geldt een fair-use policy
  • Gebruik onderstaande query om de relevante data op te halen:
query ($period: Period!, $year: Int!) {
    sjapo(period: $period) {
        id
        employee {
            id
            employeeNumber
            name
            givenNames
            prefix
            surname
            email
            dateOfBirth
            address {
                country
                region
                city
                street
                houseNumber
                houseNumberAddition
                postcode
            }
        }
        startDate
        endDate
        hours(period: $period)
        attendances(period: $period) {
            id
            startCorrected
        }
        overtimeHours(period: $period)
        illnessHours(period: $period)
        shifts(period: $period) {
            id
            start
            end
            comment
            breakDuration
            shiftType
        }
        availabilities(period: $period) {
            id
            start
            end
            isAvailable
            comment
        }
        todos(period: $period) {
            label
        }
    }
    journals(year: $year) {
        employeeName
        employeeNumber
        period
        year
        run
        department
        costCenter
        costUnit
        percentage
        generalLedgerAccount
        componentName
        debit
        credit
        total
    }
}

Bijvoorbeeld:

curl https://cockpit.eyetelligence.nl/api/api/query \
    -H 'Authorization: Bearer apitoken' \
    --data-urlencode 'query=
        query ($period: Period!, $year: Int!) {
            sjapo (period: $period) {
                id
                employee {
                    id
                    employeeNumber
                    name
                    givenNames
                }
                startDate
                endDate
                hours(period: $period)
                shifts(period: $period) {
                    id
                    start
                    end
                    comment
                    shiftType
                }
                availabilities(period: $period) {
                    id
                    start
                    end
                    isAvailable
                    comment
                }
                todos(period: $period) {
                    label
                }
            }
            journals(year: $year) {
                employeeName
                employeeNumber
                period
                year
                run
                department
                costCenter
                costUnit
                percentage
                generalLedgerAccount
                componentName
                debit
                credit
                total
            }
        }
    ' \
    --data-urlencode 'variables={"period":{"year":2023,"period":7},"year":2024}'

Omzet

Gebruik de receiptItems-query om de verkochte regels over een datumbereik op te halen: per regel het aantal, de prijzen, het btw-percentage en de categorie. De omzetdag volgt de POS-instelling van het bedrijf, zodat dit overeenkomt met de overige omzetrapportages. Optellen per dag, categorie of vestiging doe je zelf.

query ($firm: FirmInputType!, $fromDate: Date!, $toDate: Date!) {
    receiptItems(firm: $firm, fromDate: $fromDate, toDate: $toDate) {
        id
        name
        quantity
        createdAt
        taxPercentage
        totalTaxExclusivePrice
        totalTaxInclusivePrice
        category
        categoryType
    }
}

Bijvoorbeeld:

curl https://cockpit.eyetelligence.nl/api/api/query \
    -H 'Authorization: Bearer apitoken' \
    --data-urlencode 'query=
        query ($firm: FirmInputType!, $fromDate: Date!, $toDate: Date!) {
            receiptItems(firm: $firm, fromDate: $fromDate, toDate: $toDate) {
                name
                quantity
                createdAt
                totalTaxInclusivePrice
                category
            }
        }
    ' \
    --data-urlencode 'variables={"firm":{"id":1},"fromDate":"2024-01-01","toDate":"2024-01-31"}'

Diensten

Gebruik de shifts-query om de geplande diensten uit het gepubliceerde rooster op te halen over een datumbereik. Per dienst krijg je start, eind, pauze, duur, de ingeroosterde medewerker (of null bij een open dienst), de track, gepubliceerd-status en de verwachte loonkosten. Filter optioneel op shiftTypeIds en/of employeeId. Zet includeUnpublished op true om ook eigen (nog niet gepubliceerde) wijzigingen terug te zien.

query (
    $firm: FirmInputType!
    $fromDate: Date!
    $toDate: Date!
    $includeUnpublished: Boolean = false
    $shiftTypeIds: [ID]
    $employeeId: ID
) {
    shifts(
        firm: $firm
        fromDate: $fromDate
        toDate: $toDate
        includeUnpublished: $includeUnpublished
        shiftTypeIds: $shiftTypeIds
        employeeId: $employeeId
    ) {
        id
        start
        end
        breakDuration
        durationHours
        employeeId
        employee {
            id
            employeeNumber
            fullName
        }
        track
        isPublished
        expectedCost
    }
}

Medewerkers

Gebruik de employees-query om de medewerkers van een vestiging op te halen, gearchiveerde medewerkers niet meegerekend. Dit is de lijst waarmee je een naam aan een id koppelt. isWorkReady zegt of iemand op de opgegeven datum aan alle eisen voldoet om te mogen werken; ontbreekt er iets, dan staat in notWorkReadyMessages wat. Voor externe medewerkers (isExternal) staat isWorkReady altijd op true: die gegevens houdt de vestiging niet bij, dus het betekent dat er niets is gecontroleerd en niet dat alles in orde is.

query ($firm: FirmInputType!, $atDate: Date) {
    employees(firm: $firm, atDate: $atDate) {
        id
        employeeNumber
        fullName
        isExternal
        isWorkReady
        notWorkReadyMessages
    }
}

Werkcodes

Gebruik de workCodes-query om de actieve werkcodes van een vestiging op te halen. Deze codes categoriseren het soort werk op een dienst. Verwijderde codes komen niet mee.

query ($firm: FirmInputType!) {
    workCodes(firm: $firm) {
        code
        name
    }
}

Factuurcodes

Gebruik de billingCodes-query om de actieve factuurcodes van een vestiging op te halen. Deze codes zeggen aan wie een dienst wordt doorbelast. Verwijderde codes komen niet mee.

query ($firm: FirmInputType!) {
    billingCodes(firm: $firm) {
        code
        name
    }
}

Gewerkte diensten

Gebruik de attendances-query om de daadwerkelijk gewerkte diensten op te halen over een datumbereik. Alleen gereviewde diensten worden teruggegeven; startCorrected en endCorrected zijn de gecorrigeerde (gereviewde) tijden. Per dienst krijg je start, eind, pauze, netto gewerkte uren, het id van de medewerker en de werkelijke loonkosten. Voor de definitieve cijfers — inclusief de reservering van vakantie-uren — gebruik je de journals.

premiumHours geeft de toeslaguren per toeslagpercentage, zoals ook bij de uren in de cockpit te zien is. Het percentage is een fractie: 0.5 betekent 50% toeslag. totalPremiumHours is het totaal aan toeslaguren.

query ($firm: FirmInputType!, $fromDate: Date!, $toDate: Date!) {
    attendances(firm: $firm, fromDate: $fromDate, toDate: $toDate) {
        id
        startCorrected
        endCorrected
        breakDuration
        durationHoursCorrected
        employeeId
        actualCost
        totalPremiumHours
        premiumHours {
            percentage
            totalHours
            brackets {
                bracketName
                premiumHours
                componentCode
                ruleHumanReadable
            }
        }
    }
}

Publiceerwaarschuwingen

Gebruik de warnings-query om te zien wat er misgaat als het conceptrooster zou worden gepubliceerd. Dit is dezelfde controle die de planner bij het publiceren te zien krijgt: werkregels, vakantie, ziekte en beschikbaarheid. De waarschuwingen komen gegroepeerd per categorie, en per regel krijg je de diensten die de regel raakt. Er wordt niets gepubliceerd en het conceptrooster verandert niet. Laat je shiftTypeIds weg, dan tellen alle diensttypes mee.

query ($firm: FirmInputType!, $publishUntil: Date!, $shiftTypeIds: [ID]) {
    warnings(firm: $firm, publishUntil: $publishUntil, shiftTypeIds: $shiftTypeIds) {
        name
        rules {
            label
            shifts {
                id
                start
                end
                employeeId
            }
        }
    }
}

Dienstconflicten

Gebruik de shiftConflicts-query voor overlap in het conceptrooster: medewerkers die op hetzelfde moment voor twee diensten staan, binnen een vestiging (employeeOverlap) of over vestigingen heen (crossFirmOverlap). Elk conflict geeft de diensten die met elkaar botsen.

Geef je untilDate mee, dan wordt gesimuleerd wat er gebeurt als er tot en met die datum wordt gepubliceerd, waarna de simulatie wordt teruggedraaid. Ook hier wordt niets gepubliceerd.

query ($firm: FirmInputType!, $untilDate: Date, $shiftTypeIds: [ID]) {
    shiftConflicts(firm: $firm, untilDate: $untilDate, shiftTypeIds: $shiftTypeIds) {
        employeeOverlap {
            label
            shifts {
                id
                start
                end
                employeeId
            }
        }
        crossFirmOverlap {
            label
            shifts {
                id
                start
                end
                employeeId
            }
        }
    }
}

Beschikbaarheid

Gebruik de availabilities-query om over een datumbereik op te halen wanneer de medewerkers van een vestiging wel en niet kunnen werken. Dit is dezelfde beschikbaarheid die de planner ziet. Het bereik wordt opgeknipt in stukken: per stuk zegt status hoe de tijd van de medewerker eruitziet, en comment wat die erbij heeft geschreven.

status Betekenis
ILLNESS ziek
SCHEDULED al ingeroosterd
HOLIDAY goedgekeurde vakantie
NOT_AVAILABLE de medewerker heeft geantwoord dat die niet kan
AVAILABLE de medewerker heeft geantwoord dat die kan
REQUESTED gevraagd, nog geen antwoord
NOT_REQUESTED er loopt geen beschikbaarheidsvraag

Ziekte, vakantie en diensten tellen ook buiten een beschikbaarheidsvraag mee. Valt er meer tegelijk, dan wint de bovenste: een dienst op een dag dat iemand ziek is, heeft status ILLNESS. deadline is de uiterste datum waarop de medewerker nog kon antwoorden.

De velden isAvailable en eventType bestaan nog, maar zijn verouderd en verdwijnen in een volgende versie. Gebruik status.

query ($firm: FirmInputType!, $fromDate: Date!, $toDate: Date!) {
    availabilities(firm: $firm, fromDate: $fromDate, toDate: $toDate) {
        employeeId
        start
        end
        comment
        deadline
        status
    }
}

MCP

Dezelfde GraphQL API is ook beschikbaar via een MCP-server (Model Context Protocol), zodat AI-clients zoals Claude Code het schema kunnen ontdekken en zelf queries en mutaties kunnen uitvoeren.

  • Het endpoint is: https://cockpit.eyetelligence.nl/mcp
  • Het transport is streamable HTTP
  • De API-key moet als header meegegeven worden in de vorm: Authorization: Bearer [mijn token]
  • De koppeling scoping (welke firma) en rechten volgen automatisch uit de API-key, precies zoals bij de API
  • De server ondersteunt introspectie, zoeken in het schema, en het uitvoeren van queries en mutaties
  • Er geldt een fair-use policy

Configureer de server bijvoorbeeld in een .mcp.json voor Claude Code:

{
  "mcpServers": {
    "cockpit-eyetelligence": {
      "type": "http",
      "url": "https://cockpit.eyetelligence.nl/mcp",
      "headers": { "Authorization": "Bearer apitoken" }
    }
  }
}