{"openapi":"3.0.3","info":{"title":"Nakroteck Client API","version":"1.0.0","description":"First-party client API for account management, catalog lookup, hosting, domains, and invoice-first ordering."},"servers":[{"url":"https:\/\/nakroteck.net\/api\/v1","description":"Current Nakroteck environment"}],"tags":[{"name":"Developers","description":"OpenAPI specification and documentation support"},{"name":"Auth","description":"Token login and token management"},{"name":"Catalog","description":"Public products and domain pricing"},{"name":"Domains","description":"Domain search and client domain management"},{"name":"Clients","description":"Client account profile and account overview"},{"name":"Mobile","description":"Flutter app configuration, push devices, and mobile payment hints"},{"name":"Billing","description":"Invoices, payments, and orders"},{"name":"Hosting","description":"Hosting account management"},{"name":"Support","description":"Support ticket management"}],"paths":{"\/openapi.json":{"get":{"tags":["Developers"],"summary":"Get this OpenAPI document","operationId":"openApiSpec","security":[],"responses":{"200":{"description":"OpenAPI document","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/status":{"get":{"tags":["Developers"],"summary":"Get API health and version","operationId":"apiStatus","security":[],"responses":{"200":{"description":"API status","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiStatus"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/mobile\/config":{"get":{"tags":["Mobile"],"summary":"Get Flutter app configuration","operationId":"mobileConfig","security":[],"responses":{"200":{"description":"Mobile app configuration","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/MobileConfig"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/auth\/login":{"post":{"tags":["Auth"],"summary":"Issue a Sanctum bearer token","description":"Use a client portal email and password to create an API token. Paste the returned access_token into the bearer authorization field to test protected endpoints.","operationId":"login","security":[],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"email":"client@example.com","password":"secret-password","device_name":"API docs console"}}},"description":"Login credentials"},"responses":{"200":{"description":"Token issued","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LoginResponse"}}}},"403":{"description":"Account cannot access the client API","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Account cannot access the client API"}}}},"422":{"description":"Invalid credentials or validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Invalid credentials or validation error"}}}},"429":{"description":"Too many login attempts","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Too many login attempts"}}}}}}},"\/auth\/logout":{"post":{"tags":["Auth"],"summary":"Revoke the current token","operationId":"logout","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Token revoked.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Token revoked."}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/auth\/tokens":{"get":{"tags":["Auth"],"summary":"List current user tokens","operationId":"listTokens","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Token list","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/ApiToken"}}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/auth\/tokens\/{token}":{"delete":{"tags":["Auth"],"summary":"Revoke one token by ID","operationId":"revokeToken","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"integer"},"example":12}],"responses":{"200":{"description":"Token revoked.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Token revoked."}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/me":{"get":{"tags":["Auth"],"summary":"Get authenticated user and accessible clients","operationId":"me","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Current user","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/MeResponse"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/catalog\/hosting-packages":{"get":{"tags":["Catalog"],"summary":"List public hosting packages","operationId":"hostingPackages","security":[],"responses":{"200":{"description":"Hosting packages","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/HostingPackage"}}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/catalog\/domain-tlds":{"get":{"tags":["Catalog"],"summary":"List active domain TLDs and pricing","operationId":"domainTlds","security":[],"responses":{"200":{"description":"Domain TLDs","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/DomainTld"}}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/domains\/check":{"post":{"tags":["Domains"],"summary":"Check domain availability","description":"Public domain availability lookup. GH-family domains may return provisional\/manual registration states.","operationId":"checkDomain","security":[],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"domain":"example.com.gh"}}},"description":"Domain lookup"},"responses":{"200":{"description":"Domain availability result","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DomainAvailabilityResponse"}}}},"422":{"description":"Invalid domain request","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Invalid domain request"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/domains\/bulk-check":{"post":{"tags":["Domains"],"summary":"Check multiple domains","operationId":"bulkCheckDomains","security":[],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"domains":["example.com","example.com.gh"]}}},"description":"Bulk domain lookup"},"responses":{"200":{"description":"Bulk domain results","content":{"application\/json":{"schema":{"type":"object"}}}},"422":{"description":"Invalid domain list","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Invalid domain list"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients":{"get":{"tags":["Clients"],"summary":"List accessible client accounts","operationId":"listClients","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Accessible client accounts","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Client"}}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}":{"get":{"tags":["Clients"],"summary":"Get one client account","operationId":"getClient","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Client account","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Client"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/profile":{"patch":{"tags":["Clients"],"summary":"Update client profile","operationId":"updateClientProfile","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Updated client account","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Client"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"company_name":"Example Company","first_name":"Ama","last_name":"Mensah","phone":"+233550507788","country":"GH"}}},"description":"Profile fields"}}},"\/clients\/{client}\/overview":{"get":{"tags":["Clients"],"summary":"Get account overview counts","operationId":"clientOverview","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Client overview","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/dashboard":{"get":{"tags":["Clients"],"summary":"Get client dashboard summary","operationId":"clientDashboard","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Client dashboard","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/events":{"get":{"tags":["Clients"],"summary":"Get recent client events","operationId":"clientEvents","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Recent events","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/devices":{"get":{"tags":["Mobile"],"summary":"List registered mobile devices","operationId":"listMobileDevices","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Mobile devices","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/MobileDevice"}}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}},"post":{"tags":["Mobile"],"summary":"Register or update a Flutter push device","operationId":"registerMobileDevice","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Updated mobile device","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/MobileDevice"}}}}}},"201":{"description":"Registered mobile device","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/MobileDevice"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"device_id":"flutter-installation-uuid","device_name":"Ama iPhone","platform":"ios","push_provider":"apns","push_token":"push-token-from-firebase-or-apns","app_version":"1.0.0","build_number":"12","locale":"en","timezone":"Africa\/Accra","notifications_enabled":true}}},"description":"Mobile device registration"}}},"\/clients\/{client}\/devices\/{device}":{"delete":{"tags":["Mobile"],"summary":"Unregister a mobile push device","operationId":"unregisterMobileDevice","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"device","in":"path","required":true,"schema":{"type":"integer"},"example":9},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Unregistered mobile device","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/MobileDevice"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/invoices":{"get":{"tags":["Billing"],"summary":"List client invoices","operationId":"listInvoices","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Invoices","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Invoice"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/invoices\/{invoice}":{"get":{"tags":["Billing"],"summary":"Get one invoice","operationId":"getInvoice","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"invoice","in":"path","required":true,"schema":{"type":"integer"},"example":584},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Invoice","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Invoice"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/credit\/invoices":{"post":{"tags":["Billing"],"summary":"Create account credit invoice","operationId":"createCreditInvoice","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013},{"name":"Idempotency-Key","in":"header","required":true,"description":"Required for order creation, account credit invoice creation, and payment-starting endpoints. Reuse the same key only when retrying the exact same request for the same client.","schema":{"type":"string","maxLength":160},"example":"order-20260426-001"}],"responses":{"201":{"description":"Account credit invoice created","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/CreditInvoiceCreateResponse"}}}},"409":{"description":"Idempotency key conflict","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Idempotency key conflict"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"description":"Creates a normal unpaid Nakroteck invoice for account credit. The client pays the invoice using any enabled payment method, and credit is issued only after the invoice becomes paid.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"amount":50}}},"description":"Account credit amount"}}},"\/clients\/{client}\/invoices\/{invoice}\/payments\/start":{"post":{"tags":["Billing"],"summary":"Start native invoice payment","operationId":"startInvoicePayment","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"invoice","in":"path","required":true,"schema":{"type":"integer"},"example":584},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013},{"name":"Idempotency-Key","in":"header","required":true,"description":"Required for order creation, account credit invoice creation, and payment-starting endpoints. Reuse the same key only when retrying the exact same request for the same client.","schema":{"type":"string","maxLength":160},"example":"order-20260426-001"}],"responses":{"201":{"description":"Payment session created","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/PaymentStartResponse"}}}},"409":{"description":"Invoice is already paid or not payable","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Invoice is already paid or not payable"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"description":"Creates a Stripe PaymentIntent client secret or a Paystack authorization URL for an existing unpaid Nakroteck invoice. Invoice payment is still completed by gateway confirmation and webhooks.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"gateway":"stripe","save_card":false}}},"description":"Payment start request"}}},"\/clients\/{client}\/invoices\/{invoice}\/payment-status":{"get":{"tags":["Billing"],"summary":"Get invoice payment status","operationId":"invoicePaymentStatus","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"invoice","in":"path","required":true,"schema":{"type":"integer"},"example":584},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Invoice payment status","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/invoices\/{invoice}\/payment-timeline":{"get":{"tags":["Billing"],"summary":"Get invoice payment timeline","operationId":"invoicePaymentTimeline","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"invoice","in":"path","required":true,"schema":{"type":"integer"},"example":584},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Invoice payment timeline","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/InvoicePaymentTimeline"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/orders":{"get":{"tags":["Billing"],"summary":"List client orders","operationId":"listOrders","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Orders","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Order"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}},"post":{"tags":["Billing"],"summary":"Create invoice-first order","operationId":"createOrder","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"Idempotency-Key","in":"header","required":true,"description":"Required for order creation, account credit invoice creation, and payment-starting endpoints. Reuse the same key only when retrying the exact same request for the same client.","schema":{"type":"string","maxLength":160},"example":"order-20260426-001"}],"responses":{"201":{"description":"Order created","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrderCreateResponse"}}}},"409":{"description":"Idempotency key conflict","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Idempotency key conflict"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"description":"Creates an order, invoice, and pending service\/domain records. Provisioning still waits for invoice payment. Requires Idempotency-Key.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"items":[{"type":"hosting","package_id":1,"billing_cycle":"annually","domain":"example.com","domain_option":"existing"}],"payment_gateway":"paystack","notes":"Created from API documentation console."}}},"description":"Order payload"}}},"\/clients\/{client}\/payments":{"get":{"tags":["Billing"],"summary":"List client payments","operationId":"listPayments","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Payments","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Payment"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/orders\/quote":{"post":{"tags":["Billing"],"summary":"Quote an order payload","operationId":"quoteOrder","security":[{"bearerAuth":[]}],"parameters":[{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Quote result","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrderQuoteResponse"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"description":"Quotes an order for the selected client account. Use X-Client-Id to choose the account without relying on web session state.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"items":[{"type":"hosting","package_id":1,"billing_cycle":"annually","domain":"example.com","domain_option":"existing"}]}}},"description":"Quote payload"}}},"\/clients\/{client}\/hosting":{"get":{"tags":["Hosting"],"summary":"List hosting accounts","operationId":"listHosting","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Hosting accounts","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/HostingAccount"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/hosting\/{hostingAccount}":{"get":{"tags":["Hosting"],"summary":"Get hosting account","operationId":"getHosting","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"hostingAccount","in":"path","required":true,"schema":{"type":"integer"},"example":1055},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Hosting account","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/HostingAccount"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/hosting\/{hostingAccount}\/login-url":{"post":{"tags":["Hosting"],"summary":"Create hosting control panel login URL","operationId":"hostingLoginUrl","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"hostingAccount","in":"path","required":true,"schema":{"type":"integer"},"example":1055},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Temporary login URL","content":{"application\/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"expires_hint_seconds":{"type":"integer"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/hosting\/{hostingAccount}\/change-password":{"post":{"tags":["Hosting"],"summary":"Change hosting password","operationId":"changeHostingPassword","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"hostingAccount","in":"path","required":true,"schema":{"type":"integer"},"example":1055},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Password changed successfully.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Password changed successfully."}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"password":"StrongPassword123!","password_confirmation":"StrongPassword123!"}}},"description":"New password"}}},"\/clients\/{client}\/hosting\/{hostingAccount}\/cancel":{"post":{"tags":["Hosting"],"summary":"Request hosting cancellation","operationId":"cancelHosting","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"hostingAccount","in":"path","required":true,"schema":{"type":"integer"},"example":1055},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Cancellation request","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"cancellation_type":"end_of_billing_period","reason":"No longer needed"}}},"description":"Cancellation request"}}},"\/clients\/{client}\/domains":{"get":{"tags":["Domains"],"summary":"List client domains","operationId":"listClientDomains","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Domains","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Domain"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/tickets":{"get":{"tags":["Support"],"summary":"List support tickets","operationId":"listTickets","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Tickets","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Ticket"}},"links":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}},"post":{"tags":["Support"],"summary":"Create support ticket","operationId":"createTicket","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"201":{"description":"Created ticket","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Ticket"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"type":"object","properties":{"department_id":{"type":"integer","example":1},"subject":{"type":"string","example":"Need help with my hosting"},"message":{"type":"string","example":"Please help me check my hosting account."},"priority":{"type":"string","example":"medium"},"attachments[]":{"type":"array","items":{"type":"string","format":"binary"}}}}}},"description":"Ticket request with optional attachments"}}},"\/clients\/{client}\/tickets\/{ticket}":{"get":{"tags":["Support"],"summary":"Get support ticket","operationId":"getTicket","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"ticket","in":"path","required":true,"schema":{"type":"integer"},"example":123},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Ticket","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Ticket"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/tickets\/{ticket}\/reply":{"post":{"tags":["Support"],"summary":"Reply to support ticket","operationId":"replyTicket","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"ticket","in":"path","required":true,"schema":{"type":"integer"},"example":123},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Updated ticket","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Ticket"}}}}}},"409":{"description":"Ticket is closed","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Ticket is closed"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Here is the update from my side."},"attachments[]":{"type":"array","items":{"type":"string","format":"binary"}}}}}},"description":"Ticket reply with optional attachments"}}},"\/clients\/{client}\/tickets\/{ticket}\/close":{"post":{"tags":["Support"],"summary":"Close support ticket","operationId":"closeTicket","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"ticket","in":"path","required":true,"schema":{"type":"integer"},"example":123},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Closed ticket","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Ticket"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/tickets\/{ticket}\/reopen":{"post":{"tags":["Support"],"summary":"Reopen support ticket","operationId":"reopenTicket","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"ticket","in":"path","required":true,"schema":{"type":"integer"},"example":123},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Reopened ticket","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Ticket"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/domains\/{domain}":{"get":{"tags":["Domains"],"summary":"Get client domain","operationId":"getDomain","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Domain","content":{"application\/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#\/components\/schemas\/Domain"}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/domains\/{domain}\/nameservers":{"put":{"tags":["Domains"],"summary":"Update domain nameservers","operationId":"updateNameservers","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Updated domain","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"nameserver_type":"custom","nameservers":["ns1.example.com","ns2.example.com"]}}},"description":"Nameserver update"}}},"\/clients\/{client}\/domains\/{domain}\/dns":{"get":{"tags":["Domains"],"summary":"List registrar DNS records","operationId":"listDnsRecords","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"DNS records","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}},"put":{"tags":["Domains"],"summary":"Replace registrar DNS records","operationId":"updateDnsRecords","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"DNS records updated successfully.","content":{"application\/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"DNS records updated successfully."}}}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"records":[{"type":"A","name":"@","value":"192.0.2.10","ttl":3600}]}}},"description":"DNS records"}}},"\/clients\/{client}\/domains\/{domain}\/renew":{"post":{"tags":["Domains"],"summary":"Domain renewal placeholder","operationId":"renewDomain","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"422":{"description":"Use invoice-first order endpoint when renewal ordering is enabled","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Use invoice-first order endpoint when renewal ordering is enabled"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}}}},"\/clients\/{client}\/domains\/{domain}\/cancel":{"post":{"tags":["Domains"],"summary":"Request domain cancellation","operationId":"cancelDomain","security":[{"bearerAuth":[]}],"parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"integer"},"example":7013},{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"example":9759},{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013}],"responses":{"200":{"description":"Domain cancellation request","content":{"application\/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthenticated","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Unauthenticated"}}}},"403":{"description":"Forbidden","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Forbidden"}}}},"404":{"description":"Not found","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Not found"}}}},"422":{"description":"Validation error","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Validation error"}}}},"429":{"description":"Rate limit exceeded","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"},"example":{"message":"Rate limit exceeded"}}}}},"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object"},"example":{"cancel_type":"end_of_term","reason":"No longer needed"}}},"description":"Cancellation request"}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Sanctum token"}},"parameters":{"ClientIdHeader":{"name":"X-Client-Id","in":"header","required":false,"description":"Optional stateless client-account context. If both route client and header are present, they must match.","schema":{"type":"integer"},"example":7013},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Required for order creation, account credit invoice creation, and payment-starting endpoints. Reuse the same key only when retrying the exact same request for the same client.","schema":{"type":"string","maxLength":160},"example":"order-20260426-001"}},"schemas":{"Money":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"formatted":{"type":"string"},"currency":{"type":"string","example":"USD"}}},"ApiError":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"User":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"status":{"type":"string"}}},"Client":{"type":"object","properties":{"id":{"type":"integer"},"display_name":{"type":"string"},"company_name":{"type":"string","nullable":true},"email":{"type":"string","format":"email"},"status":{"type":"string"},"currency_code":{"type":"string"},"credit_balance":{"$ref":"#\/components\/schemas\/Money"},"role":{"type":"string","nullable":true}}},"HostingPackage":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"service_kind":{"type":"string"},"requires_domain":{"type":"boolean"},"pricing":{"type":"array","items":{"$ref":"#\/components\/schemas\/HostingPackagePrice"}}}},"HostingPackagePrice":{"type":"object","properties":{"billing_cycle":{"type":"string"},"price":{"$ref":"#\/components\/schemas\/Money"},"setup_fee":{"$ref":"#\/components\/schemas\/Money"}}},"DomainTld":{"type":"object","properties":{"id":{"type":"integer"},"tld":{"type":"string","example":".com"},"requires_manual_check":{"type":"boolean"},"supports_id_protection":{"type":"boolean"},"pricing":{"type":"array","items":{"$ref":"#\/components\/schemas\/DomainTldPrice"}}}},"DomainTldPrice":{"type":"object","properties":{"years":{"type":"integer"},"register":{"$ref":"#\/components\/schemas\/Money"},"renew":{"$ref":"#\/components\/schemas\/Money"},"transfer":{"$ref":"#\/components\/schemas\/Money"}}},"Invoice":{"type":"object","properties":{"id":{"type":"integer"},"invoice_number":{"type":"string"},"status":{"type":"string"},"total":{"$ref":"#\/components\/schemas\/Money"},"balance_due":{"$ref":"#\/components\/schemas\/Money"},"due_date":{"type":"string","format":"date","nullable":true},"payment_url":{"type":"string","format":"uri"}}},"Order":{"type":"object","properties":{"id":{"type":"integer"},"order_number":{"type":"string"},"status":{"type":"string"},"total":{"$ref":"#\/components\/schemas\/Money"},"invoice_id":{"type":"integer","nullable":true},"items":{"type":"array","items":{"$ref":"#\/components\/schemas\/OrderItem"}}}},"OrderItem":{"type":"object","properties":{"id":{"type":"integer"},"type":{"type":"string"},"description":{"type":"string"},"billing_cycle":{"type":"string","nullable":true},"status":{"type":"string"},"configuration":{"type":"object"}}},"Payment":{"type":"object","properties":{"id":{"type":"integer"},"amount":{"$ref":"#\/components\/schemas\/Money"},"status":{"type":"string"},"transaction_id":{"type":"string","nullable":true},"gateway":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"HostingAccount":{"type":"object","properties":{"id":{"type":"integer"},"display_name":{"type":"string"},"domain":{"type":"string","nullable":true},"hostname":{"type":"string","nullable":true},"status":{"type":"string"},"billing_cycle":{"type":"string"},"recurring_amount":{"$ref":"#\/components\/schemas\/Money"},"next_due_date":{"type":"string","format":"date","nullable":true}}},"Domain":{"type":"object","properties":{"id":{"type":"integer"},"domain_name":{"type":"string"},"status":{"type":"string"},"expiry_date":{"type":"string","format":"date","nullable":true},"next_due_date":{"type":"string","format":"date","nullable":true},"auto_renew":{"type":"boolean"},"nameservers":{"type":"array","items":{"type":"string"}}}},"ApiStatus":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"api_version":{"type":"string","example":"v1"},"time":{"type":"string","format":"date-time"},"maintenance_mode":{"type":"boolean"}}},"MobileConfig":{"type":"object","properties":{"app":{"type":"object"},"mobile":{"type":"object"},"features":{"type":"object"},"limits":{"type":"object"},"firebase":{"$ref":"#\/components\/schemas\/FirebaseAppConfig"},"payment_gateways":{"type":"array","items":{"type":"object"}},"support_departments":{"type":"array","items":{"type":"object"}},"links":{"type":"object"}}},"FirebaseAppConfig":{"type":"object","properties":{"configured":{"type":"boolean","example":true},"api_key":{"type":"string","nullable":true,"example":"AIzaSy..."},"auth_domain":{"type":"string","nullable":true,"example":"nakroteck-host.firebaseapp.com"},"project_id":{"type":"string","nullable":true,"example":"nakroteck-host"},"storage_bucket":{"type":"string","nullable":true,"example":"nakroteck-host.firebasestorage.app"},"messaging_sender_id":{"type":"string","nullable":true,"example":"998733898558"},"app_id":{"type":"string","nullable":true,"example":"1:998733898558:web:bb2aec7be6a4e926ffc26f"},"measurement_id":{"type":"string","nullable":true,"example":"G-81G7BZG750"}}},"MobileDevice":{"type":"object","properties":{"id":{"type":"integer"},"device_id":{"type":"string"},"device_name":{"type":"string","nullable":true},"platform":{"type":"string","enum":["ios","android"]},"push_provider":{"type":"string","enum":["fcm","apns"]},"has_push_token":{"type":"boolean"},"app_version":{"type":"string","nullable":true},"build_number":{"type":"string","nullable":true},"locale":{"type":"string","nullable":true},"timezone":{"type":"string","nullable":true},"notifications_enabled":{"type":"boolean"},"last_seen_at":{"type":"string","format":"date-time","nullable":true},"revoked_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time","nullable":true}}},"LoginResponse":{"type":"object","properties":{"token_type":{"type":"string","example":"Bearer"},"access_token":{"type":"string"},"abilities":{"type":"array","items":{"type":"string"}},"user":{"$ref":"#\/components\/schemas\/User"},"clients":{"type":"array","items":{"$ref":"#\/components\/schemas\/Client"}}}},"MeResponse":{"type":"object","properties":{"user":{"$ref":"#\/components\/schemas\/User"},"clients":{"type":"array","items":{"$ref":"#\/components\/schemas\/Client"}},"token":{"type":"object"}}},"ApiToken":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"abilities":{"type":"array","items":{"type":"string"}},"last_used_at":{"type":"string","format":"date-time","nullable":true},"last_used_ip":{"type":"string","nullable":true},"last_used_user_agent":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true}}},"Ticket":{"type":"object","properties":{"id":{"type":"integer"},"ticket_number":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string"},"status_label":{"type":"string"},"priority":{"type":"string"},"department":{"type":"object"},"last_reply_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"TicketAttachment":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"mime_type":{"type":"string"},"size":{"type":"integer"},"formatted_size":{"type":"string"},"url":{"type":"string","format":"uri"}}},"DomainAvailabilityResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#\/components\/schemas\/DomainAvailability"}}},"DomainAvailability":{"type":"object","properties":{"domain":{"type":"string","example":"example.com.gh"},"status":{"type":"string","example":"provisional_available"},"available":{"type":"boolean","nullable":true},"manual_registration":{"type":"boolean"},"provisional":{"type":"boolean"},"source":{"type":"string","example":"manual_fallback"},"pricing":{"type":"object","nullable":true}}},"OrderQuoteResponse":{"type":"object","properties":{"currency":{"type":"string","example":"USD"},"items":{"type":"array","items":{"type":"object"}},"totals":{"type":"object"}}},"OrderCreateResponse":{"type":"object","properties":{"message":{"type":"string"},"order":{"$ref":"#\/components\/schemas\/Order"},"invoice":{"$ref":"#\/components\/schemas\/Invoice"},"pending_services":{"type":"object"},"payment_url":{"type":"string","format":"uri"},"gateway":{"type":"object"}}},"CreditInvoiceCreateResponse":{"type":"object","properties":{"message":{"type":"string"},"invoice":{"$ref":"#\/components\/schemas\/Invoice"},"payment_url":{"type":"string","format":"uri"}}},"PaymentStartResponse":{"type":"object","properties":{"message":{"type":"string"},"invoice_id":{"type":"integer"},"invoice_number":{"type":"string"},"payment":{"oneOf":[{"$ref":"#\/components\/schemas\/StripePaymentStart"},{"$ref":"#\/components\/schemas\/PaystackPaymentStart"}]}}},"StripePaymentStart":{"type":"object","properties":{"gateway":{"type":"string","example":"stripe"},"mode":{"type":"string","example":"test"},"payment_intent_id":{"type":"string","example":"pi_123"},"client_secret":{"type":"string"},"publishable_key":{"type":"string"},"amount":{"type":"number","format":"float"},"currency":{"type":"string","example":"USD"},"mobile":{"$ref":"#\/components\/schemas\/StripeMobilePayment"}}},"StripeMobilePayment":{"type":"object","properties":{"type":{"type":"string","example":"stripe_payment_sheet"},"payment_intent_client_secret":{"type":"string"},"merchant_display_name":{"type":"string","example":"Nakroteck"},"allows_delayed_payment_methods":{"type":"boolean"},"status_url":{"type":"string","format":"uri"}}},"PaystackPaymentStart":{"type":"object","properties":{"gateway":{"type":"string","example":"paystack"},"reference":{"type":"string"},"authorization_url":{"type":"string","format":"uri"},"access_code":{"type":"string"},"amount":{"type":"number","format":"float"},"currency":{"type":"string","example":"USD"},"presentment":{"type":"object"},"callback_url":{"type":"string","format":"uri"},"mobile":{"$ref":"#\/components\/schemas\/PaystackMobilePayment"}}},"PaystackMobilePayment":{"type":"object","properties":{"type":{"type":"string","example":"paystack_webview"},"authorization_url":{"type":"string","format":"uri"},"reference":{"type":"string"},"status_url":{"type":"string","format":"uri"}}},"InvoicePaymentTimeline":{"type":"object","properties":{"invoice":{"$ref":"#\/components\/schemas\/Invoice"},"summary":{"type":"object"},"timeline":{"type":"array","items":{"$ref":"#\/components\/schemas\/PaymentTimelineEvent"}}}},"PaymentTimelineEvent":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"failed"},"type":{"type":"string","example":"payment"},"context":{"type":"string","example":"Invoice payment"},"gateway":{"type":"object"},"amount":{"$ref":"#\/components\/schemas\/Money"},"presentment":{"type":"object","nullable":true},"transaction_id":{"type":"string","nullable":true},"decline":{"type":"object"},"notes":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}