# NXTBYTE.DE Reseller-API — LLM-Referenz (llms.txt) > Maschinenlesbare Referenz der NXTBYTE Reseller-API (Konto, Abrechnung, Domains, KVM). > Kanonische URL: `https://api.nxtbyte.de/llms.txt` > Dokumentation: `https://api.nxtbyte.de/docs` · OpenAPI: `https://api.nxtbyte.de/docs-json` · llms.txt: `https://api.nxtbyte.de/llms.txt` > OpenAPI 2.1.3 — 68 Operationen. Bei Abweichung ist `/docs-json` maßgeblich. --- ## TL;DR 1. **Auth:** Header `X-API-Key: …` bei jedem Request. Live `nxtbyte-…`, Sandbox `nxtbytesand-…`. 2. **Basis-URL:** `https://api.nxtbyte.de/v1` — Pfade beginnen mit `/v1`. 3. **Scope:** Nur Ressourcen des eigenen Reseller-Kontos. Fremde IDs → `404`. 4. **productId:** aus `GET /v1/domains/pricing` bzw. `GET /v1/kvm/pricing` (bzw. Konfigurator). 5. **Preise:** Domain- und KVM-Konfigurator-Preise enthalten den NXTBYTE-Aufschlag (`markup_*_domain` / `markup_*_kvm`, analog Panel via `usesResellerPricing`). KVM-Pakete (`kvm-paket:…`) sind Shop-VK ohne zweiten Aufschlag. 6. **Bestellen ist echt:** Live-Key geht über NXTBYTE-Accounting (`user_logs` + Verfügungsrahmen), danach Provider. Kein Guthaben; Abrechnung über die monatliche Sammelrechnung. Sandbox simuliert (`sandbox:true`, `cost:0`, **kein** Verbrauch). 7. **Handles** vor Domain-Order: `POST /v1/domain/handle` → `handle` in `POST /v1/domains/order`. 8. **Antwortformat:** Erfolgreiche Antworten = JSON-Objekt oder JSON-Array (Listen ohne Wrapper). Fehler = `{statusCode,message,error}`. Ausnahme: `GET /v1/domain/preise` → `{success,data}`. 9. **501:** Features die der aktuelle Wholesale-Provider nicht unterstützt — keine Fake-Erfolge. ## Authentifizierung - Header `X-API-Key`. Keys: `https://nxtbyte.de/account/api-keys` - Voraussetzungen: Konto aktiviert, Reseller-API-Zugang (`isReseller()` / Account-Flag oder explizite Permission `customer.reseller_api`, sofern nicht `reseller_disabled`), Key aktiv; Sandbox nur mit `sandbox_enabled` oder expliziter `customer.reseller_sandbox` (sofern nicht `sandbox_disabled`). ``` BASE=https://api.nxtbyte.de/v1 KEY=nxtbyte-dein-live-key curl -H "X-API-Key: $KEY" "$BASE/me" curl -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ -d '{"query":"meinprojekt"}' "$BASE/domains/check" curl -H "X-API-Key: $KEY" "$BASE/kvm" ``` ## Fehlermodell ```json { "statusCode": 401, "message": "Ungültiger oder inaktiver API-Key.", "error": "Unauthorized" } ``` | Code | Bedeutung | |------|-----------| | 400 | Validierung / Provider-Ablehnung | | 401 | Key fehlt/ungültig / kein Reseller / Sandbox nicht freigeschaltet | | 402 | Verfügungsrahmen unzureichend oder mindestens zwei offene Monatsrechnungen | | 404 | Ressource nicht gefunden oder nicht dein Scope | | 410 | Entfernter Pfad (z. B. `/vps/preise` → `/kvm/pricing`) | | 501 | Feature für aktuellen Provider nicht verfügbar | | 503 | Reseller-API global deaktiviert | ## Sandbox - Sandbox-Key → simulierte Orders/Verwaltung in `reseller_api_sandbox_resources`, **keine** Provider-Provisionierung, **keine** Kosten, **kein** Verfügungsrahmen-Verbrauch. - Live- und Sandbox-Ressourcen sind getrennt; Katalog/Preise sind in beiden Modi gleich. - Sandbox GET read-only (wie `/v1/me`): `/v1/invoices`, `/v1/transactions` und live-`user_logs` in `/v1/orders` (zusätzlich Sandbox-Ressourcen). Schreibende Orders bleiben simuliert. - Listen antworten als JSON-Array (`[]` wenn keine Daten). `GET …/{id}` → `404` wenn unbekannt (nicht leerer Body). - Für echte Bestellungen und belastende Aktionen immer den **Live-Key** (`nxtbyte-…`) verwenden. ## Konto ``` GET /v1/me → MeResponse { id, name, email, company, balance, creditLimit, available } ``` - `balance` = immer `0` (kein Wallet) - `creditLimit` = Verfügungsrahmen (`users.reseller_credit_limit` bzw. System-Default) - `available` = Rest-Verfügungsrahmen (`creditLimit` minus monatlicher Verbrauch aktiver Produkte) ## Abrechnung ``` GET /v1/invoices → InvoiceDto[] GET /v1/invoices/{id} → InvoiceDto GET /v1/orders → OrderDto[] GET /v1/orders/{id} → OrderDto GET /v1/transactions → TransactionDto[] ``` - Rechnungen: `user_invoices` → `InvoiceDto` (`amount`/`invoiceNumber` als String; Status PENDING→SENT, CANCELED→CANCELLED); Filter `user_id` = Kundennummer - Bestellungen: `user_logs` → `OrderDto`; Sandbox-GET zusätzlich synthetische Einträge aus `reseller_api_sandbox_resources` (domains/kvm) - Transaktionen: Reseller ohne Wallet; `GET /v1/transactions` liefert immer `[]` - Sandbox und Live nutzen dieselben Tabellen für Abrechnung-GETs (read-only); leeres Array bedeutet keine Datensätze für diese Kundennummer - **Live Order/Renew:** Domain + KVM über Panel-Accounting (`ResellerApiAccounting`): Unpaid-Check + Frame-Check → `user_logs` (`cost_per_month`) → Provider. DOMAIN: Jahres-Renew in `cost_per_month` (Verbrauch /12); KVM: Monatspreis. Renew via `Request::extendProduct` ohne Wallet; Monats-Sammelrechnung ist die Forderung. ## Domains ``` GET /v1/domains/pricing POST /v1/domains/check { "query": "meinprojekt" } → { query, results:[{ productId, tld, domain, price, available }] } price = Reseller-VK (Markup); available = Provider-Check; productId aus Sync POST /v1/domains/order {productId,domain,handle,transfer?,authCode?} GET /v1/domains GET /v1/domains/{id} DELETE /v1/domains/{id} GET /v1/domains/{id}/info GET|POST /v1/domains/{id}/dns PATCH|DELETE /v1/domains/{id}/dns/{recordId} GET /v1/domains/{id}/nameservers/default PUT /v1/domains/{id}/nameservers {nameservers[]} GET /v1/domains/{id}/auth-code PATCH /v1/domains/{id}/auto-renew {autoRenew} GET /v1/domains/{id}/renewal POST /v1/domains/{id}/renew {months} # Live: 1 Jahr (Panel); Sandbox: simuliert GET|POST /v1/domain/handle GET|PATCH|DELETE /v1/domain/handle/{id} ``` ## KVM ``` GET /v1/kvm/pricing GET /v1/kvm/configurator GET /v1/kvm/configurator/{locationId}/templates POST /v1/kvm/configurator/quote|order POST /v1/kvm/order {productId} # kvm-paket:… GET /v1/kvm GET|DELETE /v1/kvm/{id} POST /v1/kvm/{id}/actions/{action} # start|stop|restart|rebuild GET /v1/kvm/{id}/manage|status|templates|console|traffic|network|incidents|renewal|firewall|backups|rescue|isos|boot POST /v1/kvm/{id}/reinstall|password-reset|backups|rescue|iso|renew PUT /v1/kvm/{id}/firewall|rdns|boot PATCH /v1/kvm/{id}/name DELETE /v1/kvm/{id}/backups/{backupId}|rescue|iso|firewall/rules/{ruleId} ``` Provider-abhängig (sonst `501`): password-reset, firewall write, rescue, iso, boot. ## Preislisten (kompakt) ``` GET /v1/domain/preise → {success,data:[{tld,create,renew,transfer,update,ownerchange,restore}]} ``` - `/domain/preise` nutzt dieselbe Markup-Quelle wie `GET /v1/domains/pricing` (Felder aus `operations`: create/renew/transfer/update/ownerchange/restore als Strings inkl. Aufschlag). - `GET /v1/domains/pricing` enthält `operations` (String-Preise) mit einmaligem NXTBYTE-Domain-Aufschlag. - `/vps/preise` wurde entfernt (`410 Gone`) — stattdessen `GET /v1/kvm/pricing` bzw. `GET /v1/kvm/configurator`. - `GET /v1/kvm/configurator` liefert `pricePerCore` / `pricePerGbRam` / … bereits mit Aufschlag (sowie Alias `prices.cores` …). Quote/Order nutzen dieselbe Markup-Logik. ## Geplant (nicht implementiert) Gameserver, TeamSpeak, Webspaces, Backups-Storage, Dedicated, Lizenzen, Tickets — Panel bleibt maßgeblich. ## Workflows ### Konto prüfen 1. `GET /v1/me` → available / creditLimit 2. `GET /v1/transactions` / `GET /v1/invoices` bei Bedarf ### Domain 1. `POST /v1/domain/handle` → handle.id 2. `POST /v1/domains/check {query}` → productId + available 3. `POST /v1/domains/order {productId,domain,handle}` 4. DNS / Nameserver unter `/v1/domains/{id}/…` ### KVM Konfigurator 1. `GET /v1/kvm/configurator` → locationId 2. `GET …/templates` → template 3. `POST …/quote` dann `POST …/order` 4. `GET /v1/kvm` / actions / renew ## Links - Landing: `https://api.nxtbyte.de/` - Dokumentation: `https://api.nxtbyte.de/docs` (Alias: `https://api.nxtbyte.de/swagger`) - OpenAPI: `https://api.nxtbyte.de/docs-json` - llms.txt: `https://api.nxtbyte.de/llms.txt` - API-Keys: `https://nxtbyte.de/account/api-keys`