blog·5 min lezen

De Nmbrs Accounting-API: wat niet in de handleiding staat

Wat we tegenkwamen bij het bouwen van een koppeling op Nmbrs Accounting, het oude Yuki: een XML-veld dat geen tekst mag zijn, een datumfilter dat op iets anders filtert, en velden die drie vormen kennen.

Bouw een koppeling op onze boekhouding die de kas, de openstaande
facturen en het inkooparchief uitleest.

In oktober bouwden we een koppeling op Nmbrs Accounting, het pakket dat tot september Yuki heette. Lezen van het grootboek, de openstaande posten en het inkooparchief, plus twee schrijfacties. Gebouwd en getest tegen de echte API, voor een café. De klant blijft anoniem en er staan hier geen bedragen, prijzen of marges.

De documentatie beschrijft de operaties netjes. Wat erin staat klopt. Wat er niet in staat, kostte ons de meeste tijd. Dit is die lijst.

Over de naamswijziging en de basis, zoals het adres, de sessie en de daglimiet, schreven we al in Yuki heet nu Nmbrs Accounting. Daar staat ook de belangrijkste regel: een verkeerd gespelde parameternaam wordt stil genegeerd, en de schrijfwijze verschilt per dienst. De verkoopdienst gebruikt sessionId en administrationId, de leesdiensten sessionID en administrationID.

Een XML-veld dat geen tekst mag zijn

Verkoopfacturen aanbieden gaat met een operatie die een veld xmlDoc heeft. Dat veld ziet eruit als een plek voor een string. Dat is het niet. Het document met de facturen moet er als echt XML-element in, als kind van xmlDoc, niet als tekst waarin de punthaken zijn weggecodeerd.

Daar komt bij dat dat document twee naamruimten nodig heeft: zijn eigen naamruimte voor verkoopfacturen en die van XML Schema Instance. Laat je een van de twee weg, dan weigert Nmbrs het hele document. De foutmelding zegt niet welke ontbreekt.

En de volgorde van de elementen telt. Er is een officieel schemabestand voor; wij valideren ons document daar in een test tegen, voordat het de deur uit gaat. Dat vangt een verkeerd geplaatst element op je eigen machine in plaats van in de boekhouding van een klant.

Het datumfilter filtert op iets anders

Het inkooparchief heeft een operatie die de documenten in een map opsomt, met een begin- en einddatum. Je verwacht dat die datums over de factuurdatum gaan. Dat doen ze niet: ze filteren op het moment dat het document binnenkwam.

Voor een boekhouding is dat een wezenlijk verschil. Een factuur van eind september die in oktober wordt gemaild, valt buiten een filter op september. Wie een maand wil afsluiten, moet dus ruimer ophalen dan de maand zelf en daarna op de documentdatum selecteren.

Pagineren werkt hier met een startregel en een aantal. Wij halen 200 per keer op en stoppen als een pagina minder dan 200 geeft. Een totaal krijg je niet.

Velden met drie vormen

De antwoorden zijn XML, en de bibliotheek die wij gebruiken maakt daar arrays van. Dat betekent dat één veld meerdere vormen kan hebben:

Een element dat één keer voorkomt, is een object. Vaker, en het is een lijst. Een parser die op een lijst rekent, breekt op het eerste contact met precies één factuur. Wij halen alles door één functie die er altijd een lijst van maakt.

Een contact-ID kan als lijst van twee gelijke waarden terugkomen. Soms als gewone tekst, soms als twee keer dezelfde waarde. Normaliseer naar de eerste niet-lege waarde.

Een soort is soms een object met een code en een tekst. Niet alleen de tekst.

Namen kunnen dubbel gecodeerd zijn. Een bedrijfsnaam met een ampersand komt terug met de codering er twee keer in. Decodeer, anders staat de naam verkeerd in je eigen scherm.

En een leuke: in het rekeningschema heet een veld descripton. Met een tikfout, in de API zelf. Schrijf je parser tegen wat de API stuurt, niet tegen wat er zou moeten staan.

Eén aanroep die bijna alles geeft

De operatie voor transactiedetails vraagt een grootboekrekening. Laat je die leeg, dan krijg je alle rekeningen in één antwoord. Een half jaar is dan een paar megabyte in één aanroep.

Dat is goud waard als je een analyse doet, want de daglimiet is 1.000 aanroepen per domein en inloggen telt mee. Eén aanroep in plaats van een lus over 400 rekeningen maakt het verschil tussen passen en niet passen. Maar let op je geheugen en je time-out: het is een groot document.

Wat je niet uit de boeking kunt halen

Twee dingen waar we tegen aanliepen bij het maken van overzichten:

De gebruiker die iets muteerde is altijd het pakket zelf. Ook bij handwerk. Je kunt dus niet zien wie wat geboekt heeft.

Er is geen invoerdatum. De transactiedatum is de boekingsdatum: de factuurdatum, de bankdatum of de weekdatum. Wanneer iemand het invoerde, staat er niet in.

En één ding dat wel werkt: de regel-ID is per regel, niet per boeking. Een boeking met vijf regels groepeer je op de documentverwijzing. Bij inkoopfacturen is dat het factuurnummer van de leverancier, wat prettig is als je wil controleren of een factuur al in de boekhouding staat.

Weigering tegenover onzekerheid

Bij het schrijven hebben we één onderscheid hard in de code gezet, en dat zouden we overal weer zo doen.

Een foutmelding van de dienst zelf is een weigering: er is niets geboekt, je mag het rustig opnieuw proberen. Een time-out, een verbroken verbinding, een serverfout zonder nette foutmelding of een antwoord dat je niet kunt lezen is iets anders. Dan weet je niet of de factuur erin staat.

Die tweede soort probeert onze koppeling nooit automatisch opnieuw. Er komt een melding met de tekst dat je eerst in de boekhouding moet kijken of de factuur er al staat. Een dubbele verkoopfactuur is veel vervelender dan een factuur die een dag later gaat.

Veelgemaakte fouten

xmlDoc vullen met tekst. Het moet een echt XML-element zijn, met beide naamruimten, in de volgorde van het schema.

Het datumfilter van het archief voor factuurdatums gebruiken. Het filtert op binnenkomst. Haal ruimer op en selecteer daarna zelf.

Per rekening een aanroep doen. Eén aanroep zonder rekeningcode geeft alles. Met 1.000 aanroepen per dag is dat geen detail.

Elke vraag met een nieuwe sessie beginnen. Inloggen telt mee in de limiet. Vraag per dienst één sessie aan en bewaar die.

Na een time-out automatisch opnieuw versturen. Een time-out is geen weigering. Laat een mens kijken voordat je een tweede factuur de boekhouding in duwt.

Wat een koppeling op dit pakket kan doen, staat op Nmbrs koppelen. Wil je zoiets voor je eigen administratie, kijk dan op maatwerk.

MK
Maarten Keizer

Oprichter van Invoker. Ruim twintig jaar hosting, systeembeheer en webdevelopment; bouwt de Claude-hosting zelf en test alles eerst op de eigen servers.

over maarten