{"components":{"schemas":{"Error":{"example":{"error":"bad_request","message":"product_id is required.","request_id":"3f6a9b1f4b2c41f6a8d5c0a3baf4f6aa"},"properties":{"error":{"description":"Error code identifier.","type":"string"},"message":{"description":"Human-readable error summary.","type":"string"},"request_id":{"description":"Request id for troubleshooting.","type":"string"}},"type":"object"},"TokenResponse":{"example":{"request_id":"3f6a9b1f4b2c41f6a8d5c0a3baf4f6aa","role":"reseller","token":"owr_live_9o2Hc5v0w4XcWm6mN8hJv1X0uHnE6m0B","token_id":12,"token_type":"Bearer","user_id":901},"properties":{"request_id":{"type":"string"},"role":{"type":"string"},"token":{"type":"string"},"token_id":{"type":"integer"},"token_type":{"type":"string"},"user_id":{"type":"integer"}},"type":"object"},"Wallet":{"example":{"balance":2515.72,"insufficient_credit_flag":false,"renewal_amount":9438.34,"request_id":"f7ac9b63d7b443f8a9ef6a0c2a61d11e","required_topup":0.0},"properties":{"balance":{"type":"number"},"insufficient_credit_flag":{"type":"boolean"},"renewal_amount":{"type":"number"},"request_id":{"type":"string"},"required_topup":{"type":"number"}},"type":"object"}},"securitySchemes":{"bearerAuth":{"bearerFormat":"API Token","scheme":"bearer","type":"http"}}},"info":{"description":"Reseller-facing API for managing reseller accounts, services, orders, hosting, invoices, and end users. Admin-only endpoints are intentionally excluded. Rate limit: 100 requests per minute per token. Use the bearer token you generate in the reseller dashboard (API Tokens page).","title":"OpenWeb Reseller API","version":"2.2.6"},"openapi":"3.0.3","paths":{"/api/v1/auth/revoke":{"post":{"description":"Revokes the bearer token used for this request.","responses":{"200":{"content":{"application/json":{"examples":{"revoked":{"value":{"message":"Token revoked.","request_id":"c1b9a2df7aab4b048ba38a63d8d7c191","success":true}}}}},"description":"Revoked"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Revoke current token","tags":["Auth"]}},"/api/v1/auth/token":{"post":{"description":"Exchange reseller email/username and password for a bearer token. Use the returned token in the Authorization header for all other calls. Example: Authorization: Bearer YOUR_TOKEN.","requestBody":{"content":{"application/json":{"examples":{"issueToken":{"summary":"Create token for CRM integration","value":{"email":"api@reseller.example","name":"CRM Integration","password":"StrongPassword1!"}}},"schema":{"properties":{"email":{"type":"string"},"name":{"type":"string"},"password":{"type":"string"}},"required":["email","password"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"token":{"value":{"request_id":"3f6a9b1f4b2c41f6a8d5c0a3baf4f6aa","role":"reseller","token":"owr_live_9o2Hc5v0w4XcWm6mN8hJv1X0uHnE6m0B","token_id":12,"token_type":"Bearer","user_id":901}}},"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Token issued"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid credentials"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not a reseller account"}},"summary":"Issue API token","tags":["Auth"]}},"/api/v1/auth/tokens":{"get":{"description":"List all tokens created by the authenticated reseller.","responses":{"200":{"content":{"application/json":{"examples":{"tokens":{"value":{"request_id":"f2e7f3d10b6b4c36b17e8f2c18a4c1b9","tokens":[{"created_at":"2025-12-01T09:00:00","id":12,"last_used_at":"2025-12-01T10:15:00","name":"CRM Integration","revoked_at":null}]}}}}},"description":"Token list"}},"security":[{"bearerAuth":[]}],"summary":"List reseller API tokens","tags":["Auth"]}},"/api/v1/endusers":{"get":{"description":"Returns endusers belonging to the reseller. Use q to search.","parameters":[{"description":"Search by username, email, or name.","in":"query","name":"q","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"endusers":{"value":{"endusers":[{"created_at":"2025-11-05T12:10:03","email":"client1@example.com","first_name":"Client","id":2101,"is_active":true,"last_name":"One","mobile_number":"0821234567","username":"client1"}],"request_id":"9bb0c0d8a65d4f7c9e322bfc84df05d3"}}}}},"description":"Enduser list"}},"security":[{"bearerAuth":[]}],"summary":"List endusers","tags":["Endusers"]},"post":{"description":"Creates a new enduser under the reseller. A welcome message is queued automatically.","requestBody":{"content":{"application/json":{"examples":{"createEnduser":{"value":{"email":"client1@example.com","first_name":"Client","last_name":"One","mobile_number":"0821234567","password":"TempPass123!","username":"client1"}}},"schema":{"type":"object"}}}},"responses":{"201":{"content":{"application/json":{"examples":{"created":{"value":{"enduser_id":2101,"request_id":"5c64c7b8e20c4f1b9c50b1f5a1d9df6f","success":true}}}}},"description":"Enduser created"}},"security":[{"bearerAuth":[]}],"summary":"Create enduser","tags":["Endusers"]}},"/api/v1/endusers/assign-product":{"post":{"description":"Creates a pending order for an existing enduser, or creates a new enduser and assigns the product in the same call. Uses the same order payload fields as /api/v1/orders.","requestBody":{"content":{"application/json":{"examples":{"assignExisting":{"value":{"enduser_id":2101,"notes":"Assign to existing enduser via API.","product_id":15,"quantity":1,"sim_card_id":982}},"createAndAssign":{"value":{"enduser":{"email":"client2@example.com","first_name":"Client","last_name":"Two","mobile_number":"0827654321","password":"TempPass123!","username":"client2"},"notes":"Create enduser and assign product in one call.","product_id":15,"quantity":1,"sim_card_id":982}}},"schema":{"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"examples":{"assigned":{"value":{"enduser_created":false,"enduser_id":2101,"invoice_id":4451,"monthly_price":399.0,"order_id":9103,"order_number":"ORD1234567","request_id":"6f9b777f52d148d2b8479d3d9fd67db2","status":"pending","success":true,"total_due_today":350.79}}}}},"description":"Order created for enduser"}},"security":[{"bearerAuth":[]}],"summary":"Assign a product to an enduser","tags":["Endusers"]}},"/api/v1/endusers/{enduser_id}":{"put":{"description":"Updates enduser profile fields or password.","parameters":[{"in":"path","name":"enduser_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"examples":{"updateEnduser":{"value":{"is_active":true,"mobile_number":"0829876543"}}},"schema":{"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"examples":{"updated":{"value":{"request_id":"d3a10e3e6b49451f8a04f302d79d79c3","success":true,"updated":{"mobile_number":"0829876543"}}}}}},"description":"Enduser updated"}},"security":[{"bearerAuth":[]}],"summary":"Update enduser","tags":["Endusers"]}},"/api/v1/health":{"get":{"description":"Simple health endpoint to confirm API availability.","responses":{"200":{"content":{"application/json":{"examples":{"healthy":{"value":{"status":"ok","timestamp":"2026-02-14T08:30:12","version":"2.2.6"}}}}},"description":"API healthy"}},"summary":"API health check","tags":["System"]}},"/api/v1/hosting/nameservers":{"post":{"description":"Update nameservers for an existing hosting service.","requestBody":{"content":{"application/json":{"examples":{"nameservers":{"value":{"ns1":"pns1.day.co.za","ns2":"pns2.day.co.za","service_id":516}}},"schema":{"properties":{"ns1":{"type":"string"},"ns2":{"type":"string"},"service_id":{"type":"integer"}},"required":["service_id","ns1","ns2"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"updated":{"value":{"domain":"chatbunny.space","nameservers":["pns1.day.co.za","pns2.day.co.za"],"request_id":"3f4f18c4f8394b7f9c4aa5c3f4dc2c4a","service_id":516,"success":true}}}}},"description":"Nameservers updated"}},"security":[{"bearerAuth":[]}],"summary":"Update hosting nameservers","tags":["Hosting"]}},"/api/v1/hosting/products":{"get":{"description":"Returns hosting products and free-domain thresholds.","responses":{"200":{"content":{"application/json":{"examples":{"products":{"value":{"products":[{"base_price":79.0,"discounted_price":74.26,"free_domain_count":1,"free_domain_max_usd":0.95,"id":105,"name":"Starter","whm_package":"starter"}],"request_id":"9f67c2a642b14d1791ae0d6d8e746b98"}}}}},"description":"Hosting products"}},"security":[{"bearerAuth":[]}],"summary":"List hosting products","tags":["Hosting"]}},"/api/v1/hosting/provision":{"post":{"description":"Registers the selected domain, updates nameservers, creates the hosting account, and creates an active hosting service. Wallet is debited, with refund on failure.","requestBody":{"content":{"application/json":{"examples":{"provision":{"value":{"address1":"Unit 1, Raddical Park, 3 Gourley Rd","address2":"Ballito","city":"Ballito","domain":"chatbunny.space","email":"john@example.com","first_name":"John","job_id":"d7b3bdd32e5049d1962fba814b21d325","last_name":"Doe","organization":"OpenWeb","phone":"0119668082","postal_code":"4399","product_id":105,"state":"KZN"}}},"schema":{"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"examples":{"provisioned":{"value":{"cpanel_password":"G7mY3!w5qP9","cpanel_username":"chatbun","domain":"chatbunny.space","due_today":9.0,"monthly_price":74.26,"nameservers":["pns1.day.co.za","pns2.day.co.za"],"request_id":"4fbac7cb61aa4e63b27aab0b8f1a8c9f","service_id":516,"success":true}}}}},"description":"Hosting provisioned"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credit"}},"security":[{"bearerAuth":[]}],"summary":"Provision hosting package (domain + WHM account)","tags":["Hosting"]}},"/api/v1/hosting/search":{"post":{"description":"Starts a hosting domain search and returns a job_id to poll for results.","requestBody":{"content":{"application/json":{"examples":{"search":{"value":{"domain":"chatbunny","product_id":105}}},"schema":{"properties":{"domain":{"type":"string"},"product_id":{"type":"integer"}},"required":["product_id","domain"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"job":{"value":{"job_id":"d7b3bdd32e5049d1962fba814b21d325","query":"chatbunny","request_id":"7e343d80d6a74e9ca1e5ad81c7e64c37","status_url":"/api/v1/hosting/search/d7b3bdd32e5049d1962fba814b21d325"}}}}},"description":"Search job started"}},"security":[{"bearerAuth":[]}],"summary":"Start hosting domain search","tags":["Hosting"]}},"/api/v1/hosting/search/{job_id}":{"get":{"description":"Returns domain search status and paginated results. Use results_page/results_per_page for pagination and free_domain_threshold to mark free domains.","parameters":[{"in":"path","name":"job_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"results_page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"results_per_page","schema":{"default":10,"type":"integer"}},{"in":"query","name":"free_domain_threshold","schema":{"default":0.95,"type":"number"}}],"responses":{"200":{"content":{"application/json":{"examples":{"results":{"value":{"com_net_results":[{"currency":"USD","domain":"chatbunny.com","is_free":false,"register_price":9.99,"register_price_zar":377.72},{"currency":"USD","domain":"chatbunny.net","is_free":false,"register_price":12.99,"register_price_zar":491.08}],"domain_choice":{"currency":"USD","domain":"chatbunny.space","is_free":true,"register_price":0.88,"register_price_zar":33.12},"free_domain_threshold":0.95,"meta":{"api_calls":20,"duration_seconds":18.9},"request_id":"7e343d80d6a74e9ca1e5ad81c7e64c37","results":[{"currency":"USD","domain":"chatbunny.space","is_free":true,"register_price":0.88,"register_price_zar":33.12},{"currency":"USD","domain":"chatbunny.site","is_free":true,"register_price":0.92,"register_price_zar":34.61}],"results_page":1,"results_pages":12,"results_total":120,"status":"ready"}}}}},"description":"Search status and results"}},"security":[{"bearerAuth":[]}],"summary":"Get hosting domain search results","tags":["Hosting"]}},"/api/v1/invoices":{"get":{"description":"Returns all invoices for the reseller with download URLs.","responses":{"200":{"content":{"application/json":{"examples":{"invoices":{"value":{"invoices":[{"billing_period_end":"2025-12-31","billing_period_start":"2025-12-01","download_url":"https://reseller.openweb.co.za/reseller/invoices/988/download","due_date":"2025-12-01","id":988,"invoice_date":"2025-12-01","invoice_number":"INV-2025-12-00988","invoice_type":"monthly_renewal","status":"paid","total_amount":9438.34}],"request_id":"ed83c232afe5461da7a16f6d0f9c74f2"}}}}},"description":"Invoices list"}},"security":[{"bearerAuth":[]}],"summary":"List invoices","tags":["Wallet"]}},"/api/v1/me":{"get":{"description":"Returns reseller profile and support-panel settings.","responses":{"200":{"content":{"application/json":{"examples":{"profile":{"value":{"company_name":"OpenWeb LTE","created_at":"2024-11-01T10:22:11","email":"lte@openweb.co.za","first_name":"LTE","id":901,"last_name":"Tester","mobile_number":"0821234567","phone":"0119668082","physical_address":"Unit 1, Raddical Park, 3 Gourley Rd, Ballito, 4399","request_id":"1f06c3a0e2f74cc8a0e32fa6bbf2b1d0","role":"reseller","support_email":"reseller@openweb.co.za","support_panel_enabled":true,"support_phone":"0119668082","support_ticket_url":"https://reseller.openweb.co.za/support","support_whatsapp":"27821234567","username":"lte@openweb.co.za"}}}}},"description":"Profile payload"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Get reseller profile","tags":["Profile"]},"put":{"description":"Update reseller contact fields and support panel details.","requestBody":{"content":{"application/json":{"examples":{"updateProfile":{"summary":"Update support panel details","value":{"support_email":"support@reseller.co.za","support_panel_enabled":true,"support_phone":"0111234567","support_ticket_url":"https://helpdesk.example.com","support_whatsapp":"27821234567"}}},"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"examples":{"updated":{"value":{"request_id":"66a0c6a5205c4a679d1348d72d7d6f9a","success":true,"updated":{"support_panel_enabled":true}}}}}},"description":"Updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Update reseller profile","tags":["Profile"]}},"/api/v1/orders":{"post":{"description":"Creates a new service order for SIM or fibre products. Hosting orders must use the hosting workflow endpoints.","requestBody":{"content":{"application/json":{"examples":{"order":{"value":{"add_static_ip":false,"notes":"Provision for client ABC","product_id":15,"quantity":1,"sim_card_id":345,"use_owp_prorata_waiver":false}}},"schema":{"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"examples":{"created":{"value":{"order_id":532,"request_id":"c4a08d2c1a3e4a7fb2f4c24fdc28d772","success":true}}}}},"description":"Order created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient credit"}},"security":[{"bearerAuth":[]}],"summary":"Create a new service order","tags":["Orders"]}},"/api/v1/products":{"get":{"description":"Returns all active products with reseller-discounted pricing.","responses":{"200":{"content":{"application/json":{"examples":{"products":{"value":{"products":[{"base_price":79.0,"category":"Telkom","category_id":3,"discounted_price":74.26,"display_title":"Uncapped 10Mbps Basic \u00b7 Telkom","id":15,"is_active":true,"name":"Uncapped 10Mbps Basic","product_type":"Data"}],"request_id":"c99f4e0f6e6b4b8c9a9f45c2fdcd1f77"}}}}},"description":"Product list"}},"security":[{"bearerAuth":[]}],"summary":"List active products","tags":["Catalog"]}},"/api/v1/services":{"get":{"description":"Returns all services for the reseller. Optional filter by status.","parameters":[{"description":"Filter by service status (active, scheduled, suspended).","in":"query","name":"status","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"examples":{"services":{"value":{"request_id":"b6a5c88f7cba4b7e85a35b6b3b7abf9b","services":[{"created_at":"2025-11-18T10:42:13","hosting_domain":null,"id":445,"monthly_fee":74.26,"msisdn":"0814285697","product_id":15,"product_name":"Uncapped 10Mbps Basic","reseller_id":901,"sim_serial":"8927020215841211","static_ip_enabled":false,"status":"active","username":"0814285697@mobile.is.co.za"}]}}}}},"description":"Service list"}},"security":[{"bearerAuth":[]}],"summary":"List services","tags":["Services"]}},"/api/v1/services/{service_id}":{"get":{"description":"Returns a single service payload.","parameters":[{"in":"path","name":"service_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"examples":{"service":{"value":{"request_id":"e52fb5db3f9c4b0b9cd4f6c6e4c7d4f1","service":{"created_at":"2025-11-18T10:42:13","hosting_domain":null,"id":445,"monthly_fee":74.26,"msisdn":"0814285697","product_id":15,"product_name":"Uncapped 10Mbps Basic","reseller_id":901,"sim_serial":"8927020215841211","static_ip_enabled":false,"status":"active","username":"0814285697@mobile.is.co.za"}}}}}},"description":"Service detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Get service","tags":["Services"]}},"/api/v1/services/{service_id}/cancel":{"post":{"description":"Schedules a cancellation based on the reseller cancellation policy. The response indicates the effective cancellation date and whether the 29th cut-off was missed.","parameters":[{"in":"path","name":"service_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"examples":{"cancel":{"value":{"reason":"Client requested cancellation"}}},"schema":{"properties":{"reason":{"type":"string"}},"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"examples":{"scheduled":{"value":{"effective_date":"2025-12-31","missed_cutoff":false,"note":"Current-month cancellation applied (cut-off is the 29th).","request_id":"c3a1b4d0f4b648b2aab6122a8b1c0b99","service_id":445,"success":true}}}}},"description":"Cancellation scheduled"}},"security":[{"bearerAuth":[]}],"summary":"Schedule service cancellation","tags":["Services"]}},"/api/v1/services/{service_id}/reactivate":{"post":{"description":"Reactivates a service previously scheduled for cancellation.","parameters":[{"in":"path","name":"service_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"examples":{"reactivated":{"value":{"request_id":"cb1a11dd7f7b48eebd4a85ea2b94bfc0","service_id":445,"status":"active","success":true}}}}},"description":"Service reactivated"}},"security":[{"bearerAuth":[]}],"summary":"Reactivate scheduled service","tags":["Services"]}},"/api/v1/sim-inventory":{"get":{"description":"Returns SIM inventory counts by category for the reseller.","responses":{"200":{"content":{"application/json":{"examples":{"inventory":{"value":{"inventory":[{"assigned":3,"available":4,"category_id":3,"category_name":"MTN Mobile 4G/5G Data","pending":1,"provisioned":1,"total":10,"used":1}],"request_id":"b00ef6f2a8bb49b7b99d2f3d4db8d6ea"}}}}},"description":"SIM inventory summary"}},"security":[{"bearerAuth":[]}],"summary":"SIM inventory summary","tags":["Catalog"]}},"/api/v1/transactions":{"get":{"description":"Returns wallet transactions. Use limit/offset for pagination.","parameters":[{"in":"query","name":"limit","schema":{"default":50,"type":"integer"}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"examples":{"transactions":{"value":{"limit":50,"offset":0,"request_id":"0d29492a8a354b41ab48a2db1378b09f","transactions":[{"amount":-79.0,"created_at":"2025-12-01T08:31:45","description":"Order #529 \u00b7 Uncapped 10Mbps Basic","id":10291,"processed_at":"2025-12-01T08:31:45","status":"completed","type":"purchase"}]}}}}},"description":"Transaction list"}},"security":[{"bearerAuth":[]}],"summary":"List wallet transactions","tags":["Wallet"]}},"/api/v1/wallet":{"get":{"description":"Returns balance, renewal amount, and insufficient-credit flags.","responses":{"200":{"content":{"application/json":{"examples":{"wallet":{"value":{"balance":2515.72,"insufficient_credit_flag":false,"renewal_amount":9438.34,"request_id":"f7ac9b63d7b443f8a9ef6a0c2a61d11e","required_topup":0.0}}},"schema":{"$ref":"#/components/schemas/Wallet"}}},"description":"Wallet"}},"security":[{"bearerAuth":[]}],"summary":"Get credit wallet","tags":["Wallet"]}}},"servers":[{"url":"https://reseller.openweb.co.za"}],"tags":[{"description":"Authenticate and manage API tokens.","name":"Auth"},{"description":"Reseller profile management.","name":"Profile"},{"description":"Credit wallet balances and transactions.","name":"Wallet"},{"description":"Products and SIM inventory.","name":"Catalog"},{"description":"Active services, cancellations, and reactivations.","name":"Services"},{"description":"Create new service orders.","name":"Orders"},{"description":"Hosting domain search and provisioning.","name":"Hosting"},{"description":"Enduser account management.","name":"Endusers"},{"description":"Health check and diagnostics.","name":"System"}]}
