Blog ·
Plesk-facturatie en -provisioning automatiseren
Van een betaalde bestelling naar een live abonnement, en van een onbetaalde factuur naar een donker abonnement. De aanroepen, de gemeten tijden, en vier vallen.
Door Provibr
Een geautomatiseerd hostingproduct heeft drie momenten waarop geld en machines elkaar raken:
- De bestelling is betaald: een abonnement moet bestaan, op het juiste serviceplan, binnen seconden.
- De factuur is onbetaald: het abonnement moet op zwart, en terugkomen op het moment dat er betaald wordt.
- Het abonnement eindigt: het moet echt verwijderd worden, inclusief zijn data.
Plesk heeft aanroepen voor alle drie. Wat hij niet heeft is iets dat beslist wanneer je ze draait, en dat is de helft die jij bouwt. Deze pagina gaat over het aan elkaar knopen van die twee, en over vier gedragingen die onschuldig zijn wanneer je er met de hand op klikt en gevaarlijk wanneer een planner ze om drie uur 's nachts draait.
Alles hier is gemeten tegen een draaiende Plesk Obsidian 18.0.80-server in augustus 2026.
De drie momenten en de aanroepen eronder
| Moment | API | Aanroep | Gemeten duur |
|---|---|---|---|
| Betaalde bestelling | REST | POST /clients daarna POST /domains | 0,6 tot 0,7 s + 4,1 tot 4,5 s |
| Onbetaald | XML | <webspace><set> met gen_setup.status | 0,78 s |
| Toch betaald | XML | dezelfde aanroep, status terug naar 0 | 0,78 s |
| Upgrade of downgrade | XML | <webspace><switch-subscription> | 1,5 s |
| Opzegging | REST | DELETE /domains/{id} daarna DELETE /clients/{id} | 7,7 s + |
| Staat lezen | XML | <webspace><get> voor de hele server | 0,33 s |
Twee van die getallen vormen het ontwerp. Een abonnement kost viereneenhalve seconde om aan te maken en bijna acht om te verwijderen. Dat is lang genoeg dat een bestelformulier moet zeggen dat er iets gebeurt, lang genoeg dat een time-outbudget dat voor een snelle API geschreven is een werkende aanroep halverwege afkapt, en lang genoeg dat twee bestellingen die samen binnenkomen echt gelijktijdig zijn in plaats van in theorie.
Let ook op de leesregel. Eén XML-aanroep geeft elk abonnement met zijn plan, status, quotum en verbruik terug in een derde van een seconde, ongeacht hoeveel het er zijn, en een facturatiesysteem verifieert voortdurend tegen het paneel.
De opschortingsval is een facturatiefout, geen API-detail
Plesk biedt twee manieren om op te schorten, en ze schrijven verschillende velden. In een hostingproduct houdt dit op wetenswaardigheid te zijn.
Gemeten, op hetzelfde abonnement:
| Wat je doet | XML gen_info.status | REST-abonnementsstatus |
|---|---|---|
| niets | 0 | active |
PUT /domains/{id}/status naar suspended | 0 | suspended |
XML <webspace><set> status 16 | 16 | suspended |
Een dunning-ronde die over REST opschort schrijft een veld waar de bulk-read niet naar kijkt, dus je platform blijft het account als actief melden. Hier is waarom dat juist de facturatie pijn doet: wanneer de factuur eindelijk betaald is, kijkt je automatisering naar zijn eigen staat, ziet een account dat nooit opgeschort werd, en hervat het niet. De klant heeft betaald en blijft donker, en niets heeft een fout vastgelegd.
De regel is één zin: schort op via het veld dat je leest. Provibr schrijft <webspace><set><gen_setup><status>, waarna beide beelden het eens zijn.
gen_info.status is een bitmask; we maten 0 voor actief, 1 voor webspace-off en 16 voor uitgeschakeld door de beheerder. Behandel alles wat niet nul is als opgeschort, de enige lezing die een waarde overleeft die nog niemand heeft gezien.
Eén eerlijk gat: we hebben het opschorten van een al opgeschort abonnement niet gemeten. Op HestiaCP is dat geval niet idempotent en geeft het een fout in de vorm van een authenticatiefout terug (precies waar een dunning-ronde dagelijks over struikelt), dus stel het op je eigen server vast voordat je erop vertrouwt.
Een verlopen sleutel ziet er precies uit als een lege server
Dit is de fout die echte schade kan aanrichten, en er is één zin voor nodig om hem te beschrijven.
De XML-API geeft HTTP 200 terug voor een verkeerde sleutel. De fout zit in het document, als code 11003. Een client die de statuscode controleert leest daarom een authenticatiefout als een geslaagde ronde die geen abonnementen vond.
Zet dat nu in een nachtelijke reconciliatietaak. Een geslaagde ronde die niets vond betekent, voor elk hostingplatform, dat elk account dat er gisteren was verwijderd is. Eén verlopen sleutel, en van de ene nacht op de andere markeert je systeem je hele klantenbestand als weg.
Er komen twee regels uit voort, en ze gelden voor elk paneel dat falen met een 200 meldt, wat, van de panelen die we geïntegreerd hebben, de meeste zijn:
- Op de XML-API draagt de statuscode helemaal geen informatie, zelfs niet over authenticatie. Parse het document.
- Een onleesbaar antwoord is onbekend, nooit leeg. Een lege server bestaat wel degelijk, en die levert één enkel leeg resultaat op in plaats van een fout. Die twee zijn werkelijk verschillend en ze uit elkaar houden is het hele werk.
REST faalt weer anders: een onbruikbare sleutel komt terug als HTTP 401 met een volledig lege body. Dus een verbindingstest moet beide oppervlakken beproeven en ze apart melden. Een groen REST-resultaat naast een zwijgende XML-API betekent dat de accountlijst, de planlijst en elke planwissel leeg blijven, en de verleidelijke conclusie is dat de klant geen accounts heeft.
De foutcode vertelt je niet wat er misging
De REST-fouten van Plesk dragen een numerieke code, en het is verleidelijk om erop te schakelen. Gemeten, hij classificeert niet:
- 1007 dekt zowel “dat domein bestaat al” als “die klantlogin bestaat al”.
- 1013 dekt zowel “er is niet zo'n serviceplan” (REST) als “domein bestaat niet” (XML).
- 0 betekent geen code, niet geen fout.
Voor een facturatie-integratie landt de schade in de retry-logica. “Domein bestaat al” na een betaalde bestelling kan betekenen dat de vorige poging half slaagde en dat je moet kijken voordat je het opnieuw probeert; “er is niet zo'n serviceplan” betekent dat de bestelling nooit zal slagen en hoort voor een mens te belanden. Ze delen een familie van codes. Dus de tekst classificeert, en die mapping hoort op precies één plek in je code te staan in plaats van bij elke aanroepplek opnieuw afgeleid te worden.
Er is ook een vijfde faalvorm: vraag REST om een route die niet bestaat en hij antwoordt met een HTML-pagina, geen JSON.
Een mislukte bestelling kan de retry blokkeren
Gemeten: een domein aanmaken tegen een serviceplan dat niet bestaat geeft HTTP 404 terug met een duidelijke melding, en het domeinobject bestaat daarna alsnog, zonder hostingtype en met een lege documentroot. Plesk maakt eerst het object aan en past daarna het plan toe, en rolt niet terug wanneer de tweede stap faalt.
In een facturatiestroom leest dat als: de klant betaalde, de provisioning mislukte, en de retry mislukt nu anders, omdat het domein in gebruik is door een account dat ze nooit ontvingen. De tweede fout ziet eruit als een dubbele bestelling, wat een van de verwarrender dingen is om vanaf een supportticket te debuggen.
Twee goedkope dingen volgen. Zoek het plan op voordat je iets aanmaakt: je hebt de planlijst al, dus zoek de naam lokaal op en laat de bestelling mislukken voordat je het paneel aanraakt, wat deze fout wegneemt in plaats van hem af te handelen. En ruim op na een mislukte aanmaak, want de wrakstukken laten liggen verandert één mislukte bestelling in een permanent geblokkeerde domeinnaam.
Ter contrast: een veldvalidatiefout zoals een dubbele klantlogin geeft HTTP 400 terug en laat niets achter. Die controle draait vóór het aanmaken; alleen het opzoeken van het plan gebeurt te laat om je te redden.
Twee aanroepen die elk een midden hebben
Een abonnement verwijderen betekent DELETE /domains/{id} en daarna DELETE /clients/{id}. Slaagt de eerste en de tweede niet, dan blijf je zitten met een klantrecord dat niets bezit: onzichtbaar in de meeste weergaven, en een dubbele-login-fout de volgende keer dat die klant terugkomt. Bij 7,7 seconden is de verwijdering ook lang genoeg voor een netwerk om hem te onderbreken, dus een opzegging verdient dezelfde behandeling als provisioning: lees het paneel achteraf terug en verifieer tegen de bulk-read, niet tegen het antwoord dat je kreeg.
Upgrades en downgrades hebben hun eigen hoek. <webspace><switch-subscription> accepteert geen plannaam, alleen de GUID of externe ID van het plan, terwijl overal elders in Plesk een pakket bij naam wordt aangeduid. Provibr houdt de naam als het ding dat mensen zien en doet de vertaling van naam naar GUID intern vanuit de planlijst die de poll al ophaalt. In plaats daarvan een GUID in je facturatiesysteem opslaan werkt tot precies het moment dat iemand een plan herbouwt.
Waar de factuur woont
De drie momenten hierboven zijn maar de helft van een hostingproduct. De andere helft is hoe je eigen rekening eruitziet.
Je betaalt voor capaciteit, per resourcetype, en een hostingaccount is er een van. Elk abonnement telt mee of het nu draait of niet; alleen een opgeschort abonnement niet. Dat is de juiste kant op voor dunning: een klant met een openstaande factuur opschorten maakt de plek vrij terwijl zijn data onaangeroerd blijft, en hervatten neemt die plek weer in.
Over je limiet gaan wordt niet geblokkeerd op het moment dat het gebeurt. Het wordt opgemerkt, je krijgt te horen welk resourcetype en met hoeveel, en je krijgt een werkdag om het op te lossen. Verloopt die, dan worden de nieuwste servers boven de limiet uitgezet, nieuwste eerst, zodat wat je het eerst bouwde blijft staan. Een tweede overschrijding binnen een week krijgt een uur in plaats van een dag, want anders zou de respijtperiode eindeloos vernieuwd kunnen worden door even onder de limiet te duiken en er weer overheen te gaan. Er wordt niets voor je weer opgestart als het opgelost is: een machine aanzetten is een beslissing, en die neemt het platform niet terwijl niemand kijkt.
Elke periode levert een proforma op die je kunt lezen en printen, met de definitieve factuur die als bestand uit de boekhouding komt. Een factuurregel legt de pakketnaam vast zoals hij op het moment van factureren was, dus een plan later hernoemen herschrijft de geschiedenis niet.
Wat Provibr doet, en wat het bewust niet doet
Provibr zit tussen je facturatie en je Plesk-server. Een abonnement is een gewone regel: bestel het, schort het op, hervat het, wissel zijn serviceplan, verwijder het. Opschorten gaat door het veld dat de poll leest. Het plan wordt opgezocht vóór de aanmaak, en een mislukte aanmaak wordt opgeruimd. Elke mutatie eindigt met het abonnement terug te lezen, dus wat opgeslagen wordt is wat waargenomen werd in plaats van wat gevraagd werd. De agent belt uitgaand vanuit je eigen netwerk, dus poort 8443 hoeft niet uit te kijken op het internet.
Wat het niet doet: de Plesk-server zelf beheren, of in een abonnement reiken. Het vraagt Plesk ook nooit om de datasets die het FTP-wachtwoord of de wachtwoordhash van de klant bevatten, die het paneel allebei in leesbare tekst afgeeft als je erom vraagt.
Lees verder
- Webhosting verkopen met Plesk: het productmodel, de twee API's, en wat we het paneel nooit vragen.
- Facturatie en licentie: capaciteit, staffelprijzen, tegoed, proforma's en wat er gebeurt boven de limiet.
- Plesk instellen: de API-sleutel, serviceplannen, webplannen en abonnementen importeren.
Gemeten tegen Plesk Obsidian 18.0.80 in augustus 2026, met antwoorden als fixtures vastgelegd. Herhaald opschorten, sleutels met resellerbereik en gedrag onder echte verkeersbelasting zijn niet gemeten, en zijn als zodanig hierboven aangegeven.