Exchange valt buiten deze API/CLI-release. Eventuele historische Exchange-voorbeelden in deze gids zijn niet beschikbaar; dit zegt niets over bestaande portaalfuncties. Zie het [actuele releasebereik](/developers/guides/release-scope?lang=nl).

# Eén afrekening voor meerdere nieuwe aankopen

De API kan 1 tot en met 25 nieuwe aankopen voor hetzelfde bedrijf samen afrekenen. Elke aanvraag wordt vooraf geprijsd met de bestaande portalbedrijfsregels. De batch voert geen reeks losse quote-commits uit: alle onderdelen worden samen voorbereid en gaan door één gedeelde bedrijfsafrekening.

## Protocol

| Methode en pad onder `/api/v1/accounts/{account}` | Gebruik |
| --- | --- |
| `POST /order-batches/quotes` | `{ "items": [{ "kind": "...", "input": { ... } }] }` valideren en serverprijzen beoordelen |
| `GET /order-batches/quotes/{quote}` | Goedgekeurde onderdelen, betaalwijze en maandfactuurafspraak bekijken |
| `POST /order-batches` | `{ "quote_id": "..." }` één keer indienen met een duurzame `Idempotency-Key` |

Beide POST-aanvragen ondersteunen `dry_run: true` of `X-Binadit-Dry-Run: true`. Een quote-preview bewaart geen quotes of geheimen. Een commit-preview maakt geen bestelling, reservering, factuur, betaling of leveringstaak.

Ondersteunde nieuwe aankopen zijn `workspace_mailbox`, `workspace_service`, `domain_register`, `domain_transfer`, `hosting_subscription`, `exchange_mailbox` en `spam_filter`. De `input` gebruikt dezelfde velden als een losse `/order-quotes`-aanvraag. Vernieuwingen, pakketwijzigingen en opzeggingen blijven via hun bestaande specifieke acties of losse quote lopen.

De server retourneert een ouderquote en onderliggende onderdelen. Onderliggende quotes hebben status `batched` en kunnen niet afzonderlijk via `/orders` worden gekocht. De ouderquote en alle onderdelen vervallen uiterlijk na tien minuten of aan het einde van de dag. Bedrijf, principal, prijzen, bestaande identiteiten en de getoonde betaal-/maandafspraak blijven aan deze goedkeuring gebonden.

## Facturatie en grenzen

De bestaande portalafspraak blijft gelden. Workspace-onderdelen gaan op de maandfactuur als het bedrijf op rekening betaalt of een geldige maandelijkse betaalafspraak heeft. Zonder die afspraak worden de resterende dagen van deze maand samen met de andere aankopen afgerekend. Er ontstaat maximaal één directe factuur en één directe betaling voor de batch. De toekomstige maandfactuur blijft een afzonderlijke bestaande bedrijfsafspraak.

`pricing.first_period_price_excl` is het bedrag dat deze afrekening direct in rekening brengt. `pricing.spending_liability_excl` telt per onderdeel het hoogste van de eerste en de volledige terugkerende periode. Een kleine pro-ratabijdrage of uitgestelde maandfactuur kan zo geen automatiseringslimiet verbergen. Er wordt één gezamenlijke limietreservering gemaakt; een onzekere fout geeft deze niet automatisch vrij.

Meerdere Hosting-aankopen met hetzelfde pakket worden in de volgorde van de goedgekeurde lijst geprojecteerd. Een gratis eerste website en betaald vervolg krijgen dus elk vooraf hun werkelijke prijs. De server controleert ook de gezamenlijke servercapaciteit. De native voorbereiding moet vervolgens exact deze volgorde, identiteiten en prijzen realiseren.

Elke identiteit mag maar één keer voorkomen. Een nieuwe mailbox met Drive kan een nieuwe pool in dezelfde Workspace aanwijzen via `drive_pool_ref`. Hosting en Exchange kunnen een domeinregistratie of verhuizing in dezelfde batch aanwijzen via `domain_ref`. Dit zijn getypeerde verwijzingen naar onderdelen van deze ene bedrijfsbestelling; losse taak-ID's, tegenstrijdige bestaande domeinselecties, dubbele identiteiten en cyclische of ongeldige verwijzingen worden vóór facturatie afgewezen. Ouders en kinderen tellen samen mee voor het maximum van 25 onderdelen. Er volgt geen stille vervanging van aangeleverde domein-, server- of account-ID's.

## Nieuwe Drive-pool en mailbox samen

Geef het poolonderdeel een unieke `ref` van maximaal 64 tekens. Het begint met een letter en bevat verder alleen letters, cijfers, `_` of `-`. De mailbox verwijst hiernaar met `input.drive_pool_ref` en `drive: true`; beide onderdelen moeten dezelfde `workspace_id` gebruiken. Een verwijzing mag ook naar een later onderdeel in de lijst wijzen.

```json
{
  "items": [
    {"kind": "workspace_mailbox", "input": {"workspace_id": 12, "domain_id": 34, "product_id": 56, "local_part": "alice", "drive": true, "drive_pool_ref": "company_pool"}},
    {"ref": "company_pool", "kind": "workspace_service", "input": {"workspace_id": 12, "product_id": 78, "service": "drive_pool"}}
  ]
}
```

Gebruik dit beveiligde JSON-invoerbestand met `binadit orders batch quote --from-file basket.json --account 1`, lees de gezamenlijke offerte en keur daarna alleen die ouderquote goed met `binadit orders batch commit QUOTE_UUID --confirm-quote QUOTE_UUID --account 1 --yes`. Er volgt één bedrijfscheckout; de bestaande afspraak bepaalt of de Workspace-regels direct of op de gezamenlijke maandfactuur worden gefactureerd.

De native portalservice bereidt de pool en mailbox samen voor, met afzonderlijke rechten per taak. Een duurzame afhankelijkheid houdt de mailbox bij alle normale taken en handmatige herstarts tegen totdat de oorspronkelijke pooltaak is afgerond én de juiste pool, omvang, organisatie en serverconfiguratie aantoonbaar vaststaan. Alleen een taakstatus `completed` is onvoldoende. Een verdwenen, geannuleerde, mislukte of afwijkende voorwaarde verschijnt als `requires_reconciliation`; onderzoek de oorspronkelijke operatie en bestel niet opnieuw. Vooruitbetaling moet voor elk onderdeel bevestigd blijven. Beoordeling/herstel van dezelfde operatie maakt geen nieuwe factuur.

## Domeinregistratie of verhuizing met Hosting en Exchange

Geef het `domain_register`- of `domain_transfer`-onderdeel een unieke `ref`. Gebruik bij Hosting en Exchange `input.domain_ref` in plaats van `domain_id` of `domain`. Het domein mag ook later in de lijst staan. De overige velden volgen de bestaande schemas; de houder en pakketten moeten al beschikbaar zijn.

```json
{
  "items": [
    {"kind": "hosting_subscription", "input": {"product_id": 10, "domain_ref": "company_domain", "manage_dns": true}},
    {"kind": "exchange_mailbox", "input": {"product_id": 20, "domain_ref": "company_domain", "alias": "alice", "local_part": "alice", "display_name": "Alice"}},
    {"ref": "company_domain", "kind": "domain_register", "input": {"domain": "voorbeeld.nl", "product_id": 30, "holder_id": 40}}
  ]
}
```

De quote toont de definitieve domeinnaam en prijzen. De database-identiteit van het nieuwe domein blijft in de quote `null`. De server reserveert bij de commit eerst de echte domeinidentiteit via dezelfde native portalservice als bestaande registraties. Daarna koppelt hij de kinderen aan precies die reservering. Alleen deze identiteit en bijbehorende versies mogen veranderen; pakket, bedrijf, server, overige goedgekeurde keuzes en kosten blijven gelijk. Vlak vóór facturatie wordt de nieuwe reservering nogmaals onder lock gecontroleerd.

Alle regels gaan door dezelfde gezamenlijke bedrijfscheckout. Vooruitbetaling houdt ook de domeinaanvraag tegen totdat de oorspronkelijke factuur betaald is. Hosting en Exchange mogen daarna pas naar hun leveranciers als de oorspronkelijke domeintaak is afgerond en de registraractivatie met dezelfde bedrijfs- en leveranciersidentiteit is bevestigd. Een verhuizing mag dagen wachten; de onderliggende taken blijven dezelfde en veroorzaken geen nieuwe afrekening. Een succesvolle aankoopcommit betekent dus nog geen afgeronde leverancierslevering: volg de oorspronkelijke operatie met `binadit operations watch OPERATION_UUID --account 1`.

Bij automatische Hosting-DNS wordt eerst de goedgekeurde domeintemplate vergeleken met de bevestigde portalzone. Pas een uitvoerende achtergrondtaak legt hiervan een ontvangstbewijs met de actuele zoneversie vast; inspectie en dry-run doen dat niet. De canonical portalwriter voegt vervolgens de Hosting-records toe met die versie en behoudt de overige records en geschiedenis. Afwijkende klantwijzigingen vóór of ná het bewijs worden niet stilzwijgend overgenomen als nieuw uitgangspunt: de bestaande taak vraagt reconciliatie. Een onduidelijk registrarantwoord, gewijzigde eigenaar, ingetrokken betaling of mislukte oudertaak kan nooit door een handmatige herstart worden omzeild.

Deze verwijzingen zijn beschikbaar in dezelfde CLI-quote/get/commit-flow als het poolvoorbeeld. Wachtwoorden worden niet in de voorbeelden meegestuurd; de bestaande beveiligde credentialworkflow levert nieuwe inloggegevens. Een bestaande externe DNS-opstelling behoudt de normale portalconfiguratie; kies de bestaande `manage_dns`-opties passend bij die opstelling. De CLI spreekt uitsluitend de portal-API aan.

## Rechten, geheimen en herstel

De verbinding heeft `orders:write` nodig om te quoten, `orders:read` om quotes te lezen en `orders:commit` om af te rekenen. Daarnaast controleert de server per onderdeel opnieuw de actuele module- en resourcerechten. Iedere leveringstaak behoudt alleen de vereiste rechten van dat eigen onderdeel. Expliciete beheerkeuzes blijven intern beheer met afzonderlijke scopes en recente sterke menselijke verificatie. Ook een interne beheerder volgt voor API-aankopen de betaalwijze van het klantbedrijf.

Wachtwoorden en verhuiscodes blijven versleuteld. Quotes, herhaalbare operatieresultaten en standaard CLI-uitvoer bevatten deze niet. Nieuwe Workspace-inloggegevens volgen de beveiligde portalworkflow.

Alle lokale resources en echte geblokkeerde taken worden vóór de eerste boekhoud-/bankaanvraag vastgelegd. De financiële poging krijgt vooraf een duurzame referentie. Pas na bevestigde afrekening worden alle lokale leveringsdelen in één transactie vrijgegeven of aan de betaling gekoppeld. Een fout in één bevestiging laat alle nog onbevestigde taken geblokkeerd.

Bij `batch_requires_reconciliation`, `billing_phase=requires_reconciliation` of `held_before_billing` moet de bestaande operatie worden onderzocht. Maak geen nieuwe batch om een onduidelijk bank-/boekhoudantwoord te omzeilen. Herhalen met dezelfde idempotentiesleutel levert de bestaande uitkomst op en maakt geen nieuwe afschrijving. Controleer de oorspronkelijke `API-BASKET-{quote}`-referentie, de bestaande factuur/betaling en de voorbereidende resources. Betaald geld tijdens een blokkade geeft geen automatische nieuwe levering of nieuwe factuur; herstel vraagt controle van diezelfde intentie.

Zie ook [betaalherstel](API-CLI-PAYMENT-RECOVERY.md), [API/CLI-gebruikersgids](API-CLI-USER-GUIDE.md) en de [releasegrens voor gevoelige API-acties](API-CLI-SENDER-CONSTRAINT.md). Deze implementatie is lokaal getest; zij is geen bewijs van een productie-uitrol of afgeronde algemene securityacceptatie.

## Rust CLI en oorspronkelijke intenties

De Rust-implementatie controleert de quote, het bedrijf, de afzonderlijke prijzen en de totale bestedingsverplichting voordat de aankoop wordt goedgekeurd. Alleen een quote maken vraagt geen aankoopbevestiging; een mandje afrekenen blijft een aparte handeling met exact dezelfde quote-UUID en expliciete goedkeuring. Een onjuist of onvolledig antwoord houdt de oorspronkelijke lokale request-intentie vast. Wachtwoorden, verhuiscodes, toekomstige privévelden en volledige invoer verschijnen niet in de prijsbeoordeling.

Er is nog geen publieke Rust CLI-release geactiveerd. De Rust-CLI bewaart de oorspronkelijke principal permanent bij iedere schrijfsleutel en verstuurt die handeling niet onder een nieuwe verbinding. Na opnieuw inloggen blijft herstel uitsluitend gekoppeld aan de bewezen oorspronkelijke operatie; lees de [gids voor oorspronkelijke operaties](/developers/guides/original-operations?lang=nl). Een nieuwe verbinding of dezelfde lokale sleutel geeft geen toestemming om een onzekere aankoop opnieuw uit te voeren. Maak geen vervangend mandje en commit geen losse kinderen.


## Hosting-DNS als onderdeel van dezelfde levering

Bij `hosting_subscription` met `manage_dns: true` gebruikt de achtergrondtaak de DNS-verbinding van het portal en de goedgekeurde hostingtemplate. Dit geldt voor een losse hostingbestelling en voor Hosting in een mandje. De API en de CLI schrijven zelf niet naar de DNS-server. De oorspronkelijke taak controleert opnieuw het bedrijf, hostingabonnement, server, templateversie, domein en de bestaande betaling voordat de DNS-voorbereiding begint.

De DNS-intentie en haar verwijzing in dezelfde oorspronkelijke hostingtaak worden samen opgeslagen. Daarna voert de canonical portalwriter iedere leveranciersstap buiten een database-transactie uit, met een vooraf opgeslagen poging en controle van het daadwerkelijke resultaat. Een ontbrekende beheerde zone wordt alleen aangemaakt als onderdeel van deze expliciet goedgekeurde Hosting-DNS-configuratie. Een onbekend antwoord wordt nooit opgelost door dezelfde leveranciersstap opnieuw te versturen.

Voor een beheerde DNS-zone worden de portalrecords, DNS-geschiedenis, hostingkoppeling, oorspronkelijke taak en oorspronkelijke order pas samen afgerond wanneer de leverancier het volledige resultaat heeft bevestigd. Bij een externe DNS-provider worden uitsluitend de voorgestelde portalrecords en hun geschiedenis opgeslagen; er wordt geen leveranciersverbinding gebruikt en dit bevestigt geen live DNS-wijziging. Stel deze records zelf in bij die externe provider. Als lokale opslag wordt geweigerd, blijft het leveranciersbewijs behouden en worden de lokale wijzigingen teruggedraaid. Een expliciete herstart van dezezelfde taak kan die lokale afronding doen zonder de bevestigde leverancierswijziging opnieuw te versturen. Bij een verloren antwoord kan herstel uitsluitend lezen om de oorspronkelijke poging te bevestigen; een eventuele vervolgstap mag alleen starten als deze nog nooit is geprobeerd.

Volg bij een bestelling via de API de oorspronkelijke operatie met `binadit operations watch OPERATION_UUID --account 123`. Een geaccepteerde aankoop betekent nog geen voltooide levering. Bij ingetrokken toestemming of een reconciliatieblokkade bewaart het systeem de oorspronkelijke taken. Een huidige bedrijfseigenaar kan met een persoonlijke, recent sterk geverifieerde verbinding en de oorspronkelijke vereiste scopes `binadit operations reapprove OPERATION_UUID --account 123 --dry-run` gebruiken om het herstel te beoordelen. De daadwerkelijke expliciete goedkeuring van diezelfde operatie gebruikt `binadit operations reapprove OPERATION_UUID --account 123 --yes`. Dit maakt geen nieuwe bestelling of factuur. Ontbreekt een verifieerbaar leveranciers-ID of verandert de oorspronkelijke bron/template/eigendom, laat support de oorspronkelijke intentie onderzoeken; maak geen nieuwe order.

Voor andere AI agents: `HostingDnsProvisioning` koppelt `hosting.create` aan `DnsRecordWriter::prepareMutation`, `executeMutation`, `reconcileMutation` en `completeMutation`. De stabiele `hosting-task-dns:<task-id>`-referentie en de versleutelde, ondertekende journal bewaken dezelfde oorspronkelijke intentie. Alleen de expliciete bestaande taakhergoedkeuring kan haar huidige grant vernieuwen; haar zakelijke payload, financiële bron en DNS-intentie blijven gelijk. Het complete-callback verwerkt uitsluitend lokale opslag en controleert de werkelijk opgeslagen hostingvlag, taakstatus en order. Verwijder geen pogingmarkers, wis geen reconciliatieblokkade om een nieuwe intentie te forceren en plaats deze fasen niet opnieuw binnen `LegacyResourceWrite` of een andere buitenste SQL-transactie.

Ook na de lokale commit worden de oorspronkelijke taakverwijzing, DNS-koppeling en orderafronding uit de schrijfverbinding teruggelezen. Een verwijderde verwijzing stopt iedere volgende leveranciersaanvraag. Als een observer ná de commit een afrondingsveld verandert, meldt de portal geen geslaagde levering. Het reeds bevestigde DNS-ontvangstbewijs blijft behouden; dezelfde taak herhalen verstuurt deze leveranciersstappen niet opnieuw. Lokale gegevens kunnen op dat moment al zijn opgeslagen. Laat de oorspronkelijke taak en het bijbehorende journal beoordelen en maak geen vervangende bestelling.

Vóór iedere Hosting-DNS-aanvraag worden na de actuele afhankelijkheids- en betaalcontrole ook de oorspronkelijke leveranciersrechten opnieuw opgehaald. Direct daarna volgt de resterende geldigheidsduur van precies die goedkeuring, zonder nieuwe databasequery of commit. Een verbinding die tijdens de laatste betaalcontrole wordt ingetrokken of verloopt, kan daardoor de DNS-stap niet alsnog versturen.
