# HTTP API

795 operations on 602 paths. Every route registered in the router is listed: 638 have a hand-written schema (utoipa) and 157 are marked *registered route* with handler and source only. The OpenAPI 3 document is [api.json](api.json). Paths are absolute.

Authentication: the browser session cookie `pelty_session` (with the `X-CSRF-Token` header on writes) or `Authorization: Bearer pelty_…` customer API keys for headless routes. Routes under `/api/v1/admin` need staff, `/api/v1/client` a customer.

## Groups

- [.well-known](#well-known) (1)
- [account](#account) (6)
- [addons](#addons) (17)
- [announcements](#announcements) (1)
- [api](#api) (1)
- [auth](#auth) (9)
- [automation](#automation) (1)
- [banned-emails](#banned-emails) (3)
- [captcha](#captcha) (2)
- [client-group-rules](#client-group-rules) (5)
- [compat](#compat) (1)
- [contact](#contact) (1)
- [contact-messages](#contact-messages) (4)
- [customers](#customers) (3)
- [docs](#docs) (3)
- [domains](#domains) (10)
- [duo](#duo) (5)
- [email-log](#email-log) (3)
- [emails](#emails) (2)
- [headless](#headless) (7)
- [includes](#includes) (1)
- [kb](#kb) (4)
- [oauth](#oauth) (7)
- [oauth-clients](#oauth-clients) (5)
- [openapi.json](#openapi-json) (1)
- [order-forms](#order-forms) (4)
- [plugins](#plugins) (2)
- [product-groups](#product-groups) (1)
- [products](#products) (4)
- [saml](#saml) (8)
- [security](#security) (9)
- [server-groups](#server-groups) (6)
- [settings](#settings) (2)
- [site](#site) (9)
- [sso](#sso) (4)
- [store](#store) (2)
- [super::account](#super-account) (4)
- [super::admin](#super-admin) (3)
- [super::admin-ops](#super-admin-ops) (19)
- [super::admin-tools](#super-admin-tools) (18)
- [super::affiliate-extras](#super-affiliate-extras) (11)
- [super::affiliates](#super-affiliates) (9)
- [super::api-keys](#super-api-keys) (6)
- [super::auth](#super-auth) (8)
- [super::automation](#super-automation) (2)
- [super::avatars](#super-avatars) (3)
- [super::billable](#super-billable) (10)
- [super::billing](#super-billing) (30)
- [super::bulk](#super-bulk) (8)
- [super::bundles](#super-bundles) (8)
- [super::campaigns](#super-campaigns) (14)
- [super::catalog](#super-catalog) (18)
- [super::client-extras](#super-client-extras) (16)
- [super::client-groups](#super-client-groups) (8)
- [super::content](#super-content) (19)
- [super::coupons](#super-coupons) (5)
- [super::credit](#super-credit) (9)
- [super::csv-import](#super-csv-import) (2)
- [super::currencies](#super-currencies) (9)
- [super::customers](#super-customers) (9)
- [super::data-feeds](#super-data-feeds) (2)
- [super::domain-pricing](#super-domain-pricing) (9)
- [super::domains](#super-domains) (26)
- [super::downloads](#super-downloads) (6)
- [super::einvoice](#super-einvoice) (4)
- [super::email-templates](#super-email-templates) (6)
- [super::exports](#super-exports) (4)
- [super::extensions](#super-extensions) (7)
- [super::fraud](#super-fraud) (3)
- [super::gateways](#super-gateways) (8)
- [super::gdpr](#super-gdpr) (8)
- [super::general-settings](#super-general-settings) (5)
- [super::health](#super-health) (2)
- [super::i18n](#super-i18n) (2)
- [super::invoice-ops](#super-invoice-ops) (13)
- [super::invoice-pdf](#super-invoice-pdf) (4)
- [super::kyc](#super-kyc) (10)
- [super::legal-entities](#super-legal-entities) (8)
- [super::link-tracking](#super-link-tracking) (4)
- [super::live-chat](#super-live-chat) (8)
- [super::mass](#super-mass) (4)
- [super::mfa](#super-mfa) (6)
- [super::modules-ext](#super-modules-ext) (10)
- [super::network-status](#super-network-status) (6)
- [super::overdue](#super-overdue) (3)
- [super::passkeys](#super-passkeys) (12)
- [super::payment-methods](#super-payment-methods) (10)
- [super::plugins](#super-plugins) (8)
- [super::projects](#super-projects) (15)
- [super::provisioning](#super-provisioning) (12)
- [super::quote-pdf](#super-quote-pdf) (2)
- [super::quotes](#super-quotes) (10)
- [super::refunds](#super-refunds) (5)
- [super::renewals](#super-renewals) (5)
- [super::reports](#super-reports) (3)
- [super::security-questions](#super-security-questions) (8)
- [super::service-changes](#super-service-changes) (10)
- [super::settings](#super-settings) (2)
- [super::setup-wizard](#super-setup-wizard) (2)
- [super::smtp](#super-smtp) (3)
- [super::ssl](#super-ssl) (3)
- [super::sso](#super-sso) (2)
- [super::staff](#super-staff) (8)
- [super::store](#super-store) (19)
- [super::support](#super-support) (18)
- [super::tax](#super-tax) (8)
- [super::ticket-attachments](#super-ticket-attachments) (3)
- [super::ticket-statuses](#super-ticket-statuses) (4)
- [super::tickets](#super-tickets) (16)
- [super::usage](#super-usage) (9)
- [super::vendor](#super-vendor) (4)
- [super::webhooks](#super-webhooks) (1)
- [support](#support) (6)
- [themes](#themes) (1)
- [tickets](#tickets) (5)
- [tlds](#tlds) (2)
- [translations](#translations) (3)
- [trusted-proxy](#trusted-proxy) (2)
- [updates](#updates) (3)
- [users](#users) (1)

## .well-known

| Method | Path | Summary |
|---|---|---|
| GET | `/.well-known/openid-configuration` | discovery (registered route) |

## account

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/account/identities` | list identities (registered route) |
| DELETE | `/api/v1/account/identities/{id}` | unlink (registered route) |
| GET | `/api/v1/account/oauth-apps` | my apps (registered route) |
| DELETE | `/api/v1/account/oauth-apps/{id}` | my revoke (registered route) |
| GET | `/api/v1/account/tos` | my tos (registered route) |
| POST | `/api/v1/account/tos/accept` | accept tos (registered route) |

## addons

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/addons/{id}/ui-token` | ui token (registered route) |
| GET | `/api/v1/addons/{id}/{*rest}` | dispatch (registered route) |
| GET | `/api/v1/admin/addons` | list (registered route) |
| GET | `/api/v1/admin/addons/mixins` | mixins list (registered route) |
| GET | `/api/v1/admin/addons/registry` | registry index (registered route) |
| GET | `/api/v1/admin/addons/registry/settings` | registry settings (registered route) |
| PUT | `/api/v1/admin/addons/registry/settings` | put registry settings (registered route) |
| POST | `/api/v1/admin/addons/registry/{id}/install` | registry install (registered route) |
| POST | `/api/v1/admin/addons/upload` | upload (registered route) |
| DELETE | `/api/v1/admin/addons/{id}` | uninstall (registered route) |
| GET | `/api/v1/admin/addons/{id}` | detail (registered route) |
| POST | `/api/v1/admin/addons/{id}/disable` | disable (registered route) |
| POST | `/api/v1/admin/addons/{id}/enable` | enable (registered route) |
| POST | `/api/v1/admin/addons/{id}/install` | install (registered route) |
| POST | `/api/v1/admin/addons/{id}/mixins` | mixins toggle (registered route) |
| GET | `/api/v1/admin/addons/{id}/settings` | get settings (registered route) |
| PUT | `/api/v1/admin/addons/{id}/settings` | put settings (registered route) |

## announcements

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/public/announcements/rss.xml` | rss (registered route) |

## api

| Method | Path | Summary |
|---|---|---|
| GET | `/api/openapi.json` | spec (registered route) |

## auth

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/auth/impersonation` | impersonation status (registered route) |
| POST | `/api/v1/auth/impersonation/stop` | stop impersonation (registered route) |
| GET | `/api/v1/auth/oauth/providers` | providers (registered route) |
| GET | `/api/v1/auth/oauth/{id}/callback` | callback (registered route) |
| GET | `/api/v1/auth/oauth/{id}/start` | start (registered route) |
| POST | `/api/v1/auth/password/change` | change password (registered route) |
| POST | `/api/v1/auth/reauth` | reauth (registered route) |
| POST | `/api/v1/auth/saml/logout` | logout (registered route) |
| GET | `/api/v1/auth/saml/providers` | providers (registered route) |

## automation

| Method | Path | Summary |
|---|---|---|
| PUT | `/api/v1/admin/automation/{kind}/settings` | put setting (registered route) |

## banned-emails

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/banned-emails` | list (registered route) |
| POST | `/api/v1/admin/banned-emails` | add (registered route) |
| DELETE | `/api/v1/admin/banned-emails/{domain}` | remove (registered route) |

## captcha

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/captcha/challenge` | challenge (registered route) |
| GET | `/api/v1/captcha/config` | public config (registered route) |

## client-group-rules

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/client-group-rules` | list (registered route) |
| POST | `/api/v1/admin/client-group-rules` | create (registered route) |
| POST | `/api/v1/admin/client-group-rules/apply` | apply (registered route) |
| DELETE | `/api/v1/admin/client-group-rules/{id}` | remove (registered route) |
| PUT | `/api/v1/admin/client-group-rules/{id}` | update (registered route) |

## compat

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/compat/whmcs` | handle (registered route) |

## contact

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/public/contact` | contact submit (registered route) |

## contact-messages

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/contact-messages` | contact list (registered route) |
| DELETE | `/api/v1/admin/contact-messages/{id}` | contact del (registered route) |
| PUT | `/api/v1/admin/contact-messages/{id}` | contact status (registered route) |
| POST | `/api/v1/admin/contact-messages/{id}/ticket` | contact to ticket (registered route) |

## customers

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/customers/{id}/close` | close customer (registered route) |
| POST | `/api/v1/admin/customers/{id}/login-as` | login as customer (registered route) |
| POST | `/api/v1/admin/customers/{id}/merge` | merge customer (registered route) |

## docs

| Method | Path | Summary |
|---|---|---|
| GET | `/docs` | {closure} (registered route) |
| GET | `/docs/` | serve (registered route) |
| GET | `/docs/{*path}` | serve (registered route) |

## domains

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/domains/bulk` | admin bulk (registered route) |
| GET | `/api/v1/admin/domains/{id}/dns` | admin dns (registered route) |
| PUT | `/api/v1/admin/domains/{id}/dns` | admin dns put (registered route) |
| POST | `/api/v1/client/domains/bulk` | client bulk (registered route) |
| PUT | `/api/v1/client/domains/{id}/addons` | client addons (registered route) |
| GET | `/api/v1/client/domains/{id}/dns` | client dns (registered route) |
| PUT | `/api/v1/client/domains/{id}/dns` | client dns put (registered route) |
| GET | `/api/v1/public/domains/check` | public check (registered route) |
| GET | `/api/v1/public/domains/tlds` | public tlds (registered route) |
| GET | `/api/v1/public/domains/whois` | public whois (registered route) |

## duo

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/security/duo` |  |
| PUT | `/api/v1/admin/security/duo` |  |
| POST | `/api/v1/admin/security/duo/test` |  |
| POST | `/api/v1/auth/duo/finish` |  |
| POST | `/api/v1/auth/duo/start` | Swap the password-step challenge for a Duo authorize URL. Health-checks |

## email-log

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/email-log` | admin list (registered route) |
| GET | `/api/v1/admin/email-log/{id}` | admin get (registered route) |
| POST | `/api/v1/admin/email-log/{id}/resend` | admin resend (registered route) |

## emails

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/client/emails` | client list (registered route) |
| GET | `/api/v1/client/emails/{id}` | client get (registered route) |

## headless

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/headless/carts` | Create a server-side cart owned by the key's customer; the response holds |
| GET | `/api/v1/headless/carts/{id}` |  |
| PUT | `/api/v1/headless/carts/{id}` |  |
| POST | `/api/v1/headless/carts/{id}/checkout` | Turn the cart into an order and a finalized invoice (fraud screening, |
| GET | `/api/v1/headless/catalog` | Catalog, enabled currencies and payment gateways in one call. |
| POST | `/api/v1/headless/invoices/{id}/pay` | Start a payment for an invoice; returns the gateway redirect/action. |
| GET | `/api/v1/headless/orders/{id}` | Order status with its invoice and provisioned services. |

## includes

| Method | Path | Summary |
|---|---|---|
| POST | `/includes/api.php` | handle (registered route) |

## kb

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/kb/articles/{id}/tags` | get tags (registered route) |
| PUT | `/api/v1/admin/kb/articles/{id}/tags` | put tags (registered route) |
| GET | `/api/v1/public/kb/tags` | tag cloud (registered route) |
| GET | `/api/v1/public/kb/tags/{tag}` | by tag (registered route) |

## oauth

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/oauth/authorize` | authorize info (registered route) |
| POST | `/api/v1/oauth/authorize` | authorize decide (registered route) |
| GET | `/oauth/jwks` | jwks (registered route) |
| POST | `/oauth/revoke` | revoke (registered route) |
| POST | `/oauth/token` | token (registered route) |
| GET | `/oauth/userinfo` | userinfo (registered route) |
| POST | `/oauth/userinfo` | userinfo (registered route) |

## oauth-clients

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/oauth-clients` | admin list (registered route) |
| POST | `/api/v1/admin/oauth-clients` | admin create (registered route) |
| DELETE | `/api/v1/admin/oauth-clients/{id}` | admin delete (registered route) |
| PATCH | `/api/v1/admin/oauth-clients/{id}` | admin update (registered route) |
| POST | `/api/v1/admin/oauth-clients/{id}/secret` | admin rotate (registered route) |

## openapi.json

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/openapi.json` | spec (registered route) |

## order-forms

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/order-forms` | admin list (registered route) |
| POST | `/api/v1/admin/order-forms` | admin create (registered route) |
| DELETE | `/api/v1/admin/order-forms/{id}` | admin delete (registered route) |
| PUT | `/api/v1/admin/order-forms/{id}` | admin update (registered route) |

## plugins

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/plugins/event-logger/recent` | {closure} (registered route) |
| GET | `/api/v1/plugins/event-logger/summary` | {closure} (registered route) |

## product-groups

| Method | Path | Summary |
|---|---|---|
| PUT | `/api/v1/admin/product-groups/{id}/order-form` | admin set group (registered route) |

## products

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/products/{id}/free-domain` | admin free get (registered route) |
| PUT | `/api/v1/admin/products/{id}/free-domain` | admin free put (registered route) |
| GET | `/api/v1/admin/products/{id}/server-group` | product group get (registered route) |
| PUT | `/api/v1/admin/products/{id}/server-group` | product group set (registered route) |

## saml

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/saml/idps` | admin list (registered route) |
| POST | `/api/v1/admin/saml/idps` | admin create (registered route) |
| DELETE | `/api/v1/admin/saml/idps/{id}` | admin delete (registered route) |
| GET | `/api/v1/admin/saml/idps/{id}` | admin get (registered route) |
| PUT | `/api/v1/admin/saml/idps/{id}` | admin update (registered route) |
| POST | `/api/v1/admin/saml/idps/{id}/rotate-key` | admin rotate key (registered route) |
| POST | `/api/v1/admin/saml/idps/{id}/validate` | admin validate (registered route) |
| POST | `/api/v1/admin/saml/metadata` | admin parse metadata (registered route) |

## security

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/security/captcha` | get policy (registered route) |
| PUT | `/api/v1/admin/security/captcha` | put policy (registered route) |
| GET | `/api/v1/admin/security/ip-rules` | list rules (registered route) |
| POST | `/api/v1/admin/security/ip-rules` | add rule (registered route) |
| DELETE | `/api/v1/admin/security/ip-rules/{id}` | delete rule (registered route) |
| GET | `/api/v1/admin/security/policy` | get policy (registered route) |
| PUT | `/api/v1/admin/security/policy` | put policy (registered route) |
| GET | `/api/v1/admin/security/tos` | list tos (registered route) |
| POST | `/api/v1/admin/security/tos` | publish tos (registered route) |

## server-groups

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/server-groups` | groups list (registered route) |
| POST | `/api/v1/admin/server-groups` | groups create (registered route) |
| DELETE | `/api/v1/admin/server-groups/{id}` | groups delete (registered route) |
| PUT | `/api/v1/admin/server-groups/{id}` | groups update (registered route) |
| GET | `/api/v1/admin/server-groups/{id}/servers` | groups members (registered route) |
| PUT | `/api/v1/admin/server-groups/{id}/servers` | groups set members (registered route) |

## settings

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/settings/ticket-auto-close` | auto close get (registered route) |
| PUT | `/api/v1/admin/settings/ticket-auto-close` | auto close put (registered route) |

## site

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/site` | admin get (registered route) |
| PUT | `/api/v1/admin/site` | admin put (registered route) |
| GET | `/api/v1/admin/site/pages` | admin pages (registered route) |
| POST | `/api/v1/admin/site/pages` | admin create (registered route) |
| DELETE | `/api/v1/admin/site/pages/{id}` | admin delete (registered route) |
| GET | `/api/v1/admin/site/pages/{id}` | admin page (registered route) |
| PUT | `/api/v1/admin/site/pages/{id}` | admin update (registered route) |
| GET | `/api/v1/public/site` | public site (registered route) |
| GET | `/api/v1/public/site/pages/{slug}` | public page (registered route) |

## sso

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/sso/saml/{id}/acs` | acs (registered route) |
| GET | `/api/v1/sso/saml/{id}/login` | login (registered route) |
| GET | `/api/v1/sso/saml/{id}/metadata` | metadata (registered route) |
| GET | `/api/v1/sso/saml/{id}/slo` | slo (registered route) |

## store

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/store/groups/{id}/order-form` | public group form (registered route) |
| GET | `/api/v1/store/order-forms/{slug}` | public form (registered route) |

## super::account

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/auth/email/resend` |  |
| POST | `/api/v1/auth/email/verify` |  |
| POST | `/api/v1/auth/password/forgot` |  |
| POST | `/api/v1/auth/password/reset` |  |

## super::admin

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/audit-logs` |  |
| GET | `/api/v1/admin/users` |  |
| POST | `/api/v1/admin/users/{id}/verify-email` | Mark a user's email address as confirmed (staff override). Idempotent. |

## super::admin-ops

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/backups` |  |
| POST | `/api/v1/admin/backups` |  |
| DELETE | `/api/v1/admin/backups/{id}` |  |
| GET | `/api/v1/admin/backups/{id}/download` |  |
| GET | `/api/v1/admin/calendar` |  |
| GET | `/api/v1/admin/customers/{id}/emails` |  |
| POST | `/api/v1/admin/emails/{job}/resend` |  |
| GET | `/api/v1/admin/inactive-clients/preview` | Dry run: who would be anonymised with this many days of inactivity. |
| POST | `/api/v1/admin/inactive-clients/run` | Run the erasure now with the saved settings (no-op when disabled). |
| GET | `/api/v1/admin/login-history` |  |
| GET | `/api/v1/admin/prefs` |  |
| PUT | `/api/v1/admin/prefs` |  |
| GET | `/api/v1/admin/settings/housekeeping` |  |
| PUT | `/api/v1/admin/settings/housekeeping` |  |
| GET | `/api/v1/admin/settings/inactive-clients` |  |
| PUT | `/api/v1/admin/settings/inactive-clients` |  |
| GET | `/api/v1/admin/settings/proforma` |  |
| PUT | `/api/v1/admin/settings/proforma` |  |
| GET | `/api/v1/admin/staff-online` |  |

## super::admin-tools

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/summary` | Client summary page (all tabs) for one customer. |
| GET | `/api/v1/admin/my-notes` |  |
| PUT | `/api/v1/admin/my-notes` |  |
| GET | `/api/v1/admin/noticeboard` |  |
| POST | `/api/v1/admin/noticeboard` |  |
| DELETE | `/api/v1/admin/noticeboard/{id}` | Authors delete their own notices; staff with settings access can delete any. |
| GET | `/api/v1/admin/notification-rules` |  |
| POST | `/api/v1/admin/notification-rules` |  |
| POST | `/api/v1/admin/notification-rules/preview` | Payload that would be POSTed for an event (no network call). |
| DELETE | `/api/v1/admin/notification-rules/{id}` |  |
| PUT | `/api/v1/admin/notification-rules/{id}` |  |
| GET | `/api/v1/admin/notification-rules/{id}/deliveries` | Delivery log for one rule (latest 100 attempts' outcome). |
| DELETE | `/api/v1/admin/notification-rules/{id}/secret` | Stop signing a webhook. |
| POST | `/api/v1/admin/notification-rules/{id}/secret` | Rotate the HMAC signing secret of a generic webhook; returned once. |
| POST | `/api/v1/admin/notification-rules/{id}/test` | Queue a test delivery through the real channel. |
| GET | `/api/v1/admin/search` | Global search across clients, invoices, services, tickets, domains, orders. |
| GET | `/api/v1/admin/system-health` |  |
| GET | `/api/v1/client/search` | Client-area search over the caller's own invoices, services, tickets, domains, plus public KB. |

## super::affiliate-extras

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/affiliates/materials` |  |
| POST | `/api/v1/admin/affiliates/materials` |  |
| DELETE | `/api/v1/admin/affiliates/materials/{id}` |  |
| PUT | `/api/v1/admin/affiliates/materials/{id}` |  |
| GET | `/api/v1/admin/affiliates/product-rates` |  |
| PUT | `/api/v1/admin/affiliates/product-rates` |  |
| DELETE | `/api/v1/admin/affiliates/product-rates/{product_id}` |  |
| GET | `/api/v1/admin/affiliates/tiers` |  |
| POST | `/api/v1/admin/affiliates/tiers` |  |
| DELETE | `/api/v1/admin/affiliates/tiers/{id}` |  |
| GET | `/api/v1/client/affiliate/materials` | Active materials plus the caller's effective commission percent and tiers. |

## super::affiliates

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/affiliates` |  |
| GET | `/api/v1/admin/affiliates/payouts` |  |
| POST | `/api/v1/admin/affiliates/payouts/{id}` |  |
| PUT | `/api/v1/admin/affiliates/{id}` |  |
| GET | `/api/v1/affiliates/r/{code}` | Referral link: remembers the code for 30 days, then sends the visitor to signup. |
| POST | `/api/v1/affiliates/track` | SPA landing (`/r/:code`): validates the code and sets the tracking cookie. |
| GET | `/api/v1/client/affiliate` |  |
| POST | `/api/v1/client/affiliate` |  |
| POST | `/api/v1/client/affiliate/payouts` |  |

## super::api-keys

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/api-keys` |  |
| DELETE | `/api/v1/admin/api-keys/{id}` |  |
| POST | `/api/v1/admin/users/{id}/api-keys/revoke-all` |  |
| GET | `/api/v1/api-keys` |  |
| POST | `/api/v1/api-keys` |  |
| DELETE | `/api/v1/api-keys/{id}` |  |

## super::auth

| Method | Path | Summary |
|---|---|---|
| PUT | `/api/v1/auth/locale` |  |
| POST | `/api/v1/auth/login` |  |
| POST | `/api/v1/auth/logout` |  |
| GET | `/api/v1/auth/me` |  |
| POST | `/api/v1/auth/register` |  |
| DELETE | `/api/v1/auth/sessions` | Sign out every other device; the calling session stays valid. |
| GET | `/api/v1/auth/sessions` |  |
| DELETE | `/api/v1/auth/sessions/{id}` |  |

## super::automation

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/automation` |  |
| POST | `/api/v1/admin/automation/{kind}/run` |  |

## super::avatars

| Method | Path | Summary |
|---|---|---|
| DELETE | `/api/v1/auth/avatar` |  |
| PUT | `/api/v1/auth/avatar` |  |
| GET | `/api/v1/avatars/{id}` | Any signed-in user may view avatars (staff lists, ticket threads). |

## super::billable

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/billable-items` |  |
| POST | `/api/v1/admin/billable-items` |  |
| DELETE | `/api/v1/admin/billable-items/{id}` |  |
| GET | `/api/v1/admin/catalog/products/{id}/billing` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/billing` |  |
| GET | `/api/v1/admin/catalog/products/{id}/fixed-term` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/fixed-term` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/stock` |  |
| POST | `/api/v1/admin/customers/{id}/billable-items/invoice` |  |
| POST | `/api/v1/admin/invoices/{id}/items` |  |

## super::billing

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/dashboard` |  |
| GET | `/api/v1/admin/invoices` |  |
| POST | `/api/v1/admin/invoices` |  |
| GET | `/api/v1/admin/invoices/{id}` |  |
| POST | `/api/v1/admin/invoices/{id}/credit-note` |  |
| POST | `/api/v1/admin/invoices/{id}/debit-note` | Issue a debit note (extra charge) against an unpaid or paid invoice. |
| POST | `/api/v1/admin/invoices/{id}/finalize` |  |
| POST | `/api/v1/admin/invoices/{id}/payments` | Record a manual payment (bank transfer…). Idempotent. |
| POST | `/api/v1/admin/invoices/{id}/void` |  |
| GET | `/api/v1/admin/jobs` |  |
| POST | `/api/v1/admin/jobs/recurring` | Enqueue a recurring-billing run now (deduplicated per minute). |
| POST | `/api/v1/admin/jobs/{id}/retry` |  |
| GET | `/api/v1/admin/orders` |  |
| DELETE | `/api/v1/admin/orders/{id}` |  |
| GET | `/api/v1/admin/orders/{id}` |  |
| POST | `/api/v1/admin/orders/{id}/approve` |  |
| POST | `/api/v1/admin/orders/{id}/cancel` |  |
| POST | `/api/v1/admin/orders/{id}/pending` |  |
| GET | `/api/v1/admin/services` |  |
| GET | `/api/v1/admin/services/{id}` |  |
| POST | `/api/v1/admin/services/{id}/action` |  |
| GET | `/api/v1/client/dashboard` |  |
| GET | `/api/v1/client/gateways` | Enabled payment gateways (ids only; never config or secrets). With |
| GET | `/api/v1/client/invoices` |  |
| GET | `/api/v1/client/invoices/{id}` |  |
| POST | `/api/v1/client/invoices/{id}/pay` | Start paying an invoice with a gateway: redirect (Stripe) or manual |
| GET | `/api/v1/client/orders` |  |
| POST | `/api/v1/client/orders` |  |
| GET | `/api/v1/client/services` |  |
| GET | `/api/v1/client/services/{id}` |  |

## super::bulk

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/invoices/bulk` | Apply one action to many invoices; returns a per-invoice result. |
| GET | `/api/v1/admin/orders/approval-queue` |  |
| POST | `/api/v1/admin/orders/bulk` |  |
| GET | `/api/v1/admin/settings/due-reminders` |  |
| PUT | `/api/v1/admin/settings/due-reminders` |  |
| GET | `/api/v1/admin/settings/order-approval` |  |
| PUT | `/api/v1/admin/settings/order-approval` |  |
| POST | `/api/v1/client/invoices/mass-pay` | Pay several of my unpaid invoices from account credit, oldest due first. |

## super::bundles

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/bundles` |  |
| POST | `/api/v1/admin/bundles` |  |
| DELETE | `/api/v1/admin/bundles/{id}` |  |
| PUT | `/api/v1/admin/bundles/{id}` |  |
| GET | `/api/v1/admin/catalog/products/{id}/recommendations` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/recommendations` |  |
| GET | `/api/v1/catalog/bundles` |  |
| GET | `/api/v1/catalog/products/{id}/recommendations` |  |

## super::campaigns

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/campaigns` |  |
| POST | `/api/v1/admin/campaigns` |  |
| POST | `/api/v1/admin/campaigns/preview` |  |
| DELETE | `/api/v1/admin/campaigns/{id}` |  |
| GET | `/api/v1/admin/campaigns/{id}` |  |
| PUT | `/api/v1/admin/campaigns/{id}` |  |
| POST | `/api/v1/admin/campaigns/{id}/cancel` |  |
| DELETE | `/api/v1/admin/campaigns/{id}/schedule` |  |
| POST | `/api/v1/admin/campaigns/{id}/schedule` | Hold a draft until `send_at`; the worker snapshots recipients then. |
| POST | `/api/v1/admin/campaigns/{id}/send` |  |
| GET | `/api/v1/client/marketing` |  |
| PUT | `/api/v1/client/marketing` |  |
| GET | `/api/v1/unsubscribe/{token}` | Lookup only: link scanners prefetching the URL never unsubscribe anyone. |
| POST | `/api/v1/unsubscribe/{token}` | No CSRF/session: the unguessable token is the credential. |

## super::catalog

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/catalog/addons` |  |
| POST | `/api/v1/admin/catalog/addons` |  |
| PUT | `/api/v1/admin/catalog/addons/{id}` |  |
| GET | `/api/v1/admin/catalog/groups` |  |
| POST | `/api/v1/admin/catalog/groups` |  |
| GET | `/api/v1/admin/catalog/products` |  |
| POST | `/api/v1/admin/catalog/products` |  |
| PATCH | `/api/v1/admin/catalog/products/{id}` |  |
| GET | `/api/v1/admin/catalog/products/{id}/fields` |  |
| POST | `/api/v1/admin/catalog/products/{id}/fields` |  |
| DELETE | `/api/v1/admin/catalog/products/{id}/fields/{field}` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/fields/{field}` |  |
| POST | `/api/v1/admin/catalog/products/{id}/options` |  |
| DELETE | `/api/v1/admin/catalog/products/{id}/options/{option}` |  |
| PUT | `/api/v1/admin/catalog/products/{id}/prices` |  |
| GET | `/api/v1/catalog` |  |
| GET | `/api/v1/catalog/products/{id}/extras` | Addons and customer-visible custom fields offered for one product. |
| GET | `/api/v1/currencies` |  |

## super::client-extras

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/client-fields` |  |
| POST | `/api/v1/admin/client-fields` |  |
| DELETE | `/api/v1/admin/client-fields/{id}` |  |
| PUT | `/api/v1/admin/client-fields/{id}` |  |
| GET | `/api/v1/admin/customers/{id}/fields` |  |
| PUT | `/api/v1/admin/customers/{id}/fields` |  |
| GET | `/api/v1/admin/customers/{id}/notes` |  |
| POST | `/api/v1/admin/customers/{id}/notes` |  |
| DELETE | `/api/v1/admin/customers/{id}/notes/{note}` |  |
| PUT | `/api/v1/admin/customers/{id}/notes/{note}` |  |
| GET | `/api/v1/admin/todos` |  |
| POST | `/api/v1/admin/todos` |  |
| DELETE | `/api/v1/admin/todos/{id}` |  |
| PUT | `/api/v1/admin/todos/{id}` |  |
| GET | `/api/v1/client/fields` |  |
| PUT | `/api/v1/client/fields` |  |

## super::client-groups

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/client-groups` |  |
| POST | `/api/v1/admin/client-groups` |  |
| DELETE | `/api/v1/admin/client-groups/{id}` |  |
| PUT | `/api/v1/admin/client-groups/{id}` |  |
| GET | `/api/v1/admin/client-groups/{id}/members` |  |
| POST | `/api/v1/admin/client-groups/{id}/members` |  |
| DELETE | `/api/v1/admin/client-groups/{id}/members/{customer_id}` |  |
| POST | `/api/v1/admin/customers/{id}/group` |  |

## super::content

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/announcements` |  |
| POST | `/api/v1/admin/announcements` |  |
| DELETE | `/api/v1/admin/announcements/{id}` |  |
| PUT | `/api/v1/admin/announcements/{id}` |  |
| GET | `/api/v1/admin/kb/articles` |  |
| POST | `/api/v1/admin/kb/articles` |  |
| DELETE | `/api/v1/admin/kb/articles/{id}` |  |
| GET | `/api/v1/admin/kb/articles/{id}` |  |
| PUT | `/api/v1/admin/kb/articles/{id}` |  |
| GET | `/api/v1/admin/kb/categories` |  |
| POST | `/api/v1/admin/kb/categories` |  |
| DELETE | `/api/v1/admin/kb/categories/{id}` |  |
| PUT | `/api/v1/admin/kb/categories/{id}` |  |
| GET | `/api/v1/public/announcements` |  |
| GET | `/api/v1/public/announcements/{id}` |  |
| GET | `/api/v1/public/kb` |  |
| GET | `/api/v1/public/kb/articles/{slug}` |  |
| POST | `/api/v1/public/kb/articles/{slug}/vote` |  |
| GET | `/api/v1/public/kb/suggest` | Up to 5 published articles related to `q` (used while opening a ticket). |

## super::coupons

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/coupons` |  |
| POST | `/api/v1/admin/coupons` |  |
| DELETE | `/api/v1/admin/coupons/{id}` |  |
| PUT | `/api/v1/admin/coupons/{id}` |  |
| POST | `/api/v1/client/coupons/check` | Validate a code for the order form. Returns only what the customer needs. |

## super::credit

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/credit` |  |
| POST | `/api/v1/admin/customers/{id}/credit` |  |
| POST | `/api/v1/admin/invoices/{id}/apply-credit` |  |
| GET | `/api/v1/admin/settings/add-funds` |  |
| PUT | `/api/v1/admin/settings/add-funds` |  |
| GET | `/api/v1/client/credit` |  |
| GET | `/api/v1/client/credit/add-funds` |  |
| POST | `/api/v1/client/credit/add-funds` | Create a deposit invoice; once paid (any gateway) the amount is credited. |
| POST | `/api/v1/client/invoices/{id}/apply-credit` |  |

## super::csv-import

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/import/csv/analyze` | Headers, a 5-row preview, the target fields and a suggested mapping. |
| POST | `/api/v1/admin/import/csv/run` | Validate every row; unless `dry_run`, import them all-or-nothing. |

## super::currencies

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/currencies` |  |
| POST | `/api/v1/admin/currencies` |  |
| GET | `/api/v1/admin/currencies/rates/history` |  |
| GET | `/api/v1/admin/currencies/rates/settings` |  |
| PUT | `/api/v1/admin/currencies/rates/settings` |  |
| POST | `/api/v1/admin/currencies/rates/update` |  |
| POST | `/api/v1/admin/currencies/sync-prices` |  |
| PUT | `/api/v1/admin/currencies/{code}` |  |
| POST | `/api/v1/admin/currencies/{code}/default` |  |

## super::customers

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers` |  |
| POST | `/api/v1/admin/customers` |  |
| GET | `/api/v1/admin/customers/{id}` |  |
| PATCH | `/api/v1/admin/customers/{id}` |  |
| GET | `/api/v1/client/contacts` |  |
| POST | `/api/v1/client/contacts` |  |
| DELETE | `/api/v1/client/contacts/{id}` |  |
| GET | `/api/v1/client/profile` |  |
| PUT | `/api/v1/client/profile` |  |

## super::data-feeds

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/feeds/products/{slug}` |  |
| GET | `/api/v1/feeds/tlds/{tld}` | Registration price for one year of a TLD. |

## super::domain-pricing

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/domains/costs` |  |
| GET | `/api/v1/admin/domains/margins` |  |
| PUT | `/api/v1/admin/domains/margins` |  |
| GET | `/api/v1/admin/domains/premium-settings` |  |
| PUT | `/api/v1/admin/domains/premium-settings` |  |
| POST | `/api/v1/admin/domains/sync-prices` |  |
| GET | `/api/v1/admin/domains/tld-fields` |  |
| PUT | `/api/v1/admin/domains/tld-fields/{tld}` |  |
| GET | `/api/v1/client/domains/fields` |  |

## super::domains

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/domains` |  |
| POST | `/api/v1/admin/domains/run` |  |
| GET | `/api/v1/admin/domains/{id}` |  |
| PATCH | `/api/v1/admin/domains/{id}` |  |
| POST | `/api/v1/admin/domains/{id}/registrant-verification` |  |
| POST | `/api/v1/admin/domains/{id}/sync` |  |
| GET | `/api/v1/admin/registrars` |  |
| GET | `/api/v1/admin/settings/domain-defaults` |  |
| PUT | `/api/v1/admin/settings/domain-defaults` |  |
| GET | `/api/v1/admin/settings/registrant-verification` |  |
| PUT | `/api/v1/admin/settings/registrant-verification` |  |
| GET | `/api/v1/admin/tlds` |  |
| PUT | `/api/v1/admin/tlds` |  |
| DELETE | `/api/v1/admin/tlds/{tld}/{currency}` |  |
| GET | `/api/v1/client/domains` |  |
| POST | `/api/v1/client/domains` |  |
| GET | `/api/v1/client/domains/check` |  |
| GET | `/api/v1/client/domains/tlds` |  |
| GET | `/api/v1/client/domains/{id}` |  |
| PUT | `/api/v1/client/domains/{id}/auto-renew` |  |
| PUT | `/api/v1/client/domains/{id}/contact` |  |
| POST | `/api/v1/client/domains/{id}/epp` | Reveal the transfer-out (EPP) code. Audited; owner only, active domains. |
| PUT | `/api/v1/client/domains/{id}/nameservers` |  |
| POST | `/api/v1/client/domains/{id}/registrant-verification/resend` |  |
| POST | `/api/v1/client/domains/{id}/renew` |  |
| POST | `/api/v1/public/domains/verify-registrant` | E-mail link target: confirms the registrant address (all its pending domains). |

## super::downloads

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/downloads` |  |
| POST | `/api/v1/admin/downloads` |  |
| DELETE | `/api/v1/admin/downloads/{id}` |  |
| GET | `/api/v1/admin/downloads/{id}` |  |
| GET | `/api/v1/client/downloads` |  |
| GET | `/api/v1/client/downloads/{id}` |  |

## super::einvoice

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/invoices/{id}/ubl` | UBL 2.1 (Peppol BIS 3.0 / CIUS-RO) XML of any issued invoice. |
| GET | `/api/v1/admin/settings/einvoice` |  |
| PUT | `/api/v1/admin/settings/einvoice` |  |
| GET | `/api/v1/client/invoices/{id}/ubl` | UBL 2.1 (Peppol BIS 3.0 / CIUS-RO) XML of one of the caller's issued invoices. |

## super::email-templates

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/email-templates` |  |
| PUT | `/api/v1/admin/email-templates/{name}/enabled` | Switch a template on or off; disabled templates are never queued. |
| DELETE | `/api/v1/admin/email-templates/{name}/{locale}` |  |
| PUT | `/api/v1/admin/email-templates/{name}/{locale}` |  |
| POST | `/api/v1/admin/email-templates/{name}/{locale}/preview` |  |
| POST | `/api/v1/admin/email-templates/{name}/{locale}/test` | Queue the saved template, with sample data, to the signed-in admin. |

## super::exports

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/exports/invoices.csv` |  |
| GET | `/api/v1/admin/exports/payments.csv` |  |
| GET | `/api/v1/admin/reports/tax` |  |
| GET | `/api/v1/admin/reports/tax.csv` |  |

## super::extensions

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/gateways/{id}/rules` | Fee, amount-limit and currency rules for one gateway. |
| PUT | `/api/v1/admin/gateways/{id}/rules` |  |
| GET | `/api/v1/admin/plugins` |  |
| PUT | `/api/v1/admin/plugins/{id}` |  |
| PUT | `/api/v1/admin/themes/active` |  |
| GET | `/api/v1/themes` |  |
| GET | `/api/v1/themes/active` | Active theme, sanitized: whitelisted tokens with validated CSS values. |

## super::fraud

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/fraud/checks` |  |
| GET | `/api/v1/admin/settings/fraud` |  |
| PUT | `/api/v1/admin/settings/fraud` |  |

## super::gateways

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/gateways` | Built-in gateways plus operator-defined custom ones; never secret values. |
| POST | `/api/v1/admin/gateways/custom` |  |
| GET | `/api/v1/admin/gateways/deliveries` |  |
| DELETE | `/api/v1/admin/gateways/{id}` |  |
| PUT | `/api/v1/admin/gateways/{id}` |  |
| POST | `/api/v1/admin/gateways/{id}/test-webhook` | Verify + parse a pasted webhook without applying it (logged as a test). |
| GET | `/api/v1/client/invoices/{id}/gateways` | Gateways usable for this invoice (currency + amount limits). Ids/names only. |
| POST | `/api/v1/client/payments/{id}/complete` | Payer returned from the provider: capture/check and apply (idempotent). |

## super::gdpr

| Method | Path | Summary |
|---|---|---|
| DELETE | `/api/v1/account/privacy/erasure` |  |
| GET | `/api/v1/account/privacy/erasure` |  |
| POST | `/api/v1/account/privacy/erasure` |  |
| GET | `/api/v1/account/privacy/export` |  |
| GET | `/api/v1/admin/gdpr/requests` |  |
| POST | `/api/v1/admin/gdpr/requests/{id}/approve` |  |
| POST | `/api/v1/admin/gdpr/requests/{id}/reject` |  |
| GET | `/api/v1/admin/gdpr/users/{id}/export` |  |

## super::general-settings

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/custom-code` |  |
| PUT | `/api/v1/admin/custom-code` |  |
| GET | `/api/v1/admin/general-settings` |  |
| PUT | `/api/v1/admin/general-settings` |  |
| GET | `/api/v1/public/general` | Public subset: maintenance banner, localisation, ordering flags, social links, custom code. |

## super::health

| Method | Path | Summary |
|---|---|---|
| GET | `/healthz` | Liveness: process is up. |
| GET | `/readyz` | Readiness: database reachable. |

## super::i18n

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/i18n` | Available languages plus the one negotiated for this request. |
| GET | `/api/v1/i18n/{lang}` | All messages for a language (falls back to `en` per key on the client). |

## super::invoice-ops

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/mergeable-invoices` |  |
| GET | `/api/v1/admin/gift-cards` |  |
| POST | `/api/v1/admin/gift-cards` |  |
| POST | `/api/v1/admin/gift-cards/{id}/disable` |  |
| POST | `/api/v1/admin/invoices/merge` |  |
| POST | `/api/v1/admin/invoices/{id}/duplicate` |  |
| GET | `/api/v1/admin/invoices/{id}/notes` |  |
| PUT | `/api/v1/admin/invoices/{id}/notes` |  |
| POST | `/api/v1/admin/invoices/{id}/split` |  |
| GET | `/api/v1/admin/transactions` |  |
| PATCH | `/api/v1/admin/transactions/{id}` |  |
| POST | `/api/v1/client/gift-cards/redeem` |  |
| POST | `/api/v1/client/invoices/merge` | Client-side merge (WHMCS "mass payment"): combine own unpaid invoices into |

## super::invoice-pdf

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/invoices/{id}/pdf` |  |
| GET | `/api/v1/admin/settings/invoice-branding` |  |
| PUT | `/api/v1/admin/settings/invoice-branding` |  |
| GET | `/api/v1/client/invoices/{id}/pdf` |  |

## super::kyc

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/kyc` |  |
| PUT | `/api/v1/admin/customers/{id}/kyc` |  |
| GET | `/api/v1/admin/kyc` |  |
| GET | `/api/v1/admin/kyc/documents/{id}/download` |  |
| POST | `/api/v1/admin/kyc/documents/{id}/review` |  |
| GET | `/api/v1/admin/kyc/settings` |  |
| PUT | `/api/v1/admin/kyc/settings` |  |
| GET | `/api/v1/client/kyc` |  |
| POST | `/api/v1/client/kyc/documents` | Raw body upload. PNG/JPEG/WebP/PDF only. |
| DELETE | `/api/v1/client/kyc/documents/{id}` |  |

## super::legal-entities

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/legal-entity` |  |
| PUT | `/api/v1/admin/customers/{id}/legal-entity` |  |
| GET | `/api/v1/admin/legal-entities` |  |
| POST | `/api/v1/admin/legal-entities` |  |
| DELETE | `/api/v1/admin/legal-entities/default` |  |
| DELETE | `/api/v1/admin/legal-entities/{id}` |  |
| PUT | `/api/v1/admin/legal-entities/{id}` |  |
| POST | `/api/v1/admin/legal-entities/{id}/default` |  |

## super::link-tracking

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/tracked-links` |  |
| POST | `/api/v1/admin/tracked-links` |  |
| DELETE | `/api/v1/admin/tracked-links/{id}` |  |
| GET | `/api/v1/go/{slug}` | Public: count the click and 303 to the stored target. |

## super::live-chat

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/chats` |  |
| POST | `/api/v1/admin/chats/{id}/close` |  |
| GET | `/api/v1/admin/chats/{id}/messages` |  |
| POST | `/api/v1/admin/chats/{id}/messages` |  |
| POST | `/api/v1/chat/sessions` |  |
| POST | `/api/v1/chat/sessions/{id}/close` |  |
| GET | `/api/v1/chat/sessions/{id}/messages` |  |
| POST | `/api/v1/chat/sessions/{id}/messages` |  |

## super::mass

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/mass/customers` |  |
| POST | `/api/v1/admin/mass/domains` |  |
| POST | `/api/v1/admin/mass/services` |  |
| POST | `/api/v1/admin/mass/tickets` |  |

## super::mfa

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/auth/mfa` |  |
| POST | `/api/v1/auth/mfa/backup-codes` | Replace all backup codes; returned once. |
| POST | `/api/v1/auth/mfa/disable` | Turn 2FA off; needs the password and a current code (or a backup code). |
| POST | `/api/v1/auth/mfa/enable` |  |
| POST | `/api/v1/auth/mfa/setup` | Start enrolment: a fresh pending secret, replaced on each call until enabled. |
| POST | `/api/v1/auth/mfa/verify` | Second login step. Max 5 attempts per challenge, 5 minute lifetime. |

## super::modules-ext

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/module-log` |  |
| GET | `/api/v1/admin/module-queue` |  |
| POST | `/api/v1/admin/module-queue/{id}/retry` |  |
| GET | `/api/v1/admin/servers/health` |  |
| POST | `/api/v1/admin/servers/health/check` |  |
| POST | `/api/v1/admin/services/{id}/module/custom` |  |
| GET | `/api/v1/admin/services/{id}/module/usage` |  |
| GET | `/api/v1/client/services/{id}/module` |  |
| POST | `/api/v1/client/services/{id}/module/{action}` |  |
| POST | `/api/v1/licensing/verify` | Public. Bind on first use, then verify; the response is HMAC-signed with |

## super::network-status

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/network-issues` |  |
| POST | `/api/v1/admin/network-issues` |  |
| DELETE | `/api/v1/admin/network-issues/{id}` |  |
| PUT | `/api/v1/admin/network-issues/{id}` |  |
| POST | `/api/v1/admin/network-issues/{id}/updates` |  |
| GET | `/api/v1/public/network-status` | Public: open issues plus anything resolved in the last 14 days. |

## super::overdue

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/overdue/run` | Run today's overdue automation now (idempotent with the daily job). |
| GET | `/api/v1/admin/settings/overdue` |  |
| PUT | `/api/v1/admin/settings/overdue` |  |

## super::passkeys

| Method | Path | Summary |
|---|---|---|
| DELETE | `/api/v1/admin/users/{id}/passkeys` | Revoke every passkey of a user (lost device / compromised account). |
| GET | `/api/v1/admin/users/{id}/passkeys` |  |
| GET | `/api/v1/auth/passkeys` |  |
| POST | `/api/v1/auth/passkeys/discover/finish` |  |
| POST | `/api/v1/auth/passkeys/discover/start` | Usernameless sign-in: empty `allowCredentials`, the authenticator picks a |
| POST | `/api/v1/auth/passkeys/login/finish` | Passwordless sign-in. A user-verified passkey counts as both factors. |
| POST | `/api/v1/auth/passkeys/login/start` |  |
| POST | `/api/v1/auth/passkeys/reauth/finish` | Step-up with a passkey instead of password + code. |
| POST | `/api/v1/auth/passkeys/reauth/start` |  |
| POST | `/api/v1/auth/passkeys/register/finish` |  |
| POST | `/api/v1/auth/passkeys/register/start` | Enrolment needs the password (and 2FA code when enabled) again. |
| DELETE | `/api/v1/auth/passkeys/{id}` |  |

## super::payment-methods

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/autopay/run` | Run auto-pay now (idempotent with the daily job). |
| PUT | `/api/v1/admin/customers/{id}/auto-pay` |  |
| GET | `/api/v1/admin/customers/{id}/payment-methods` |  |
| GET | `/api/v1/admin/settings/autopay` |  |
| PUT | `/api/v1/admin/settings/autopay` |  |
| PUT | `/api/v1/client/billing/auto-pay` |  |
| GET | `/api/v1/client/billing/payment-methods` |  |
| POST | `/api/v1/client/billing/payment-methods` |  |
| DELETE | `/api/v1/client/billing/payment-methods/{id}` |  |
| POST | `/api/v1/client/billing/payment-methods/{id}/default` |  |

## super::plugins

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/plugins/{id}/deliveries` |  |
| POST | `/api/v1/admin/plugins/{id}/deliveries/{did}/redeliver` |  |
| GET | `/api/v1/admin/plugins/{id}/settings` |  |
| PUT | `/api/v1/admin/plugins/{id}/settings` |  |
| GET | `/api/v1/admin/plugins/{id}/webhook` |  |
| PUT | `/api/v1/admin/plugins/{id}/webhook` |  |
| POST | `/api/v1/admin/plugins/{id}/webhook/secret` | Generate a new signing secret and return it once. |
| GET | `/api/v1/plugins/ui` |  |

## super::projects

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/projects` |  |
| POST | `/api/v1/admin/projects` |  |
| DELETE | `/api/v1/admin/projects/{id}` |  |
| GET | `/api/v1/admin/projects/{id}` |  |
| PUT | `/api/v1/admin/projects/{id}` |  |
| POST | `/api/v1/admin/projects/{id}/invoice-time` | Bill all unbilled billable time on one invoice. |
| DELETE | `/api/v1/admin/projects/{id}/links` |  |
| POST | `/api/v1/admin/projects/{id}/links` |  |
| POST | `/api/v1/admin/projects/{id}/tasks` |  |
| DELETE | `/api/v1/admin/projects/{id}/tasks/{task}` |  |
| PUT | `/api/v1/admin/projects/{id}/tasks/{task}` |  |
| POST | `/api/v1/admin/projects/{id}/time` |  |
| DELETE | `/api/v1/admin/projects/{id}/time/{entry}` |  |
| GET | `/api/v1/client/projects` |  |
| GET | `/api/v1/client/projects/{id}` |  |

## super::provisioning

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/products/{id}/module` |  |
| PUT | `/api/v1/admin/products/{id}/module` |  |
| GET | `/api/v1/admin/provisioning/modules` |  |
| GET | `/api/v1/admin/servers` |  |
| POST | `/api/v1/admin/servers` |  |
| DELETE | `/api/v1/admin/servers/{id}` |  |
| PUT | `/api/v1/admin/servers/{id}` |  |
| GET | `/api/v1/admin/servers/{id}/accounts` | Accounts on the panel, each with the service it is linked to (if any). |
| POST | `/api/v1/admin/servers/{id}/import` | Create services for panel accounts (no provisioning call; status `ok`). |
| POST | `/api/v1/admin/servers/{id}/test` | Check the stored credentials against the panel. Returns `{ok, error?}` |
| POST | `/api/v1/admin/services/{id}/module` | Manually (re)run a module action. Does not change the billing status. |
| GET | `/api/v1/admin/services/{id}/provisioning` |  |

## super::quote-pdf

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/quotes/{id}/pdf` |  |
| GET | `/api/v1/client/quotes/{id}/pdf` |  |

## super::quotes

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/quotes` |  |
| POST | `/api/v1/admin/quotes` |  |
| DELETE | `/api/v1/admin/quotes/{id}` |  |
| GET | `/api/v1/admin/quotes/{id}` |  |
| PUT | `/api/v1/admin/quotes/{id}` |  |
| POST | `/api/v1/admin/quotes/{id}/send` |  |
| GET | `/api/v1/client/quotes` |  |
| GET | `/api/v1/client/quotes/{id}` |  |
| POST | `/api/v1/client/quotes/{id}/accept` |  |
| POST | `/api/v1/client/quotes/{id}/decline` |  |

## super::refunds

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/invoices/{id}/refunds` |  |
| POST | `/api/v1/admin/payments/{id}/refunds` |  |
| GET | `/api/v1/admin/settings/reversal` |  |
| PUT | `/api/v1/admin/settings/reversal` |  |
| GET | `/api/v1/client/invoices/{id}/refunds` |  |

## super::renewals

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/services/{id}/renew-now` |  |
| GET | `/api/v1/admin/settings/on-demand-renewals` |  |
| PUT | `/api/v1/admin/settings/on-demand-renewals` |  |
| GET | `/api/v1/client/renewals/config` |  |
| POST | `/api/v1/client/services/{id}/renew-now` |  |

## super::reports

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/reports` |  |
| GET | `/api/v1/admin/reports/library` | Available reports grouped by category. |
| GET | `/api/v1/admin/reports/library/{key}` | Run one report over whole months `[from, to]` as JSON or CSV. |

## super::security-questions

| Method | Path | Summary |
|---|---|---|
| DELETE | `/api/v1/account/security-question` |  |
| GET | `/api/v1/account/security-question` |  |
| PUT | `/api/v1/account/security-question` |  |
| GET | `/api/v1/admin/customers/{id}/security-question` | Which question the client chose (not the answer). |
| POST | `/api/v1/admin/customers/{id}/security-question/verify` | Check a caller's answer. Rate limited per customer and audited. |
| GET | `/api/v1/admin/security-questions` |  |
| POST | `/api/v1/admin/security-questions` |  |
| DELETE | `/api/v1/admin/security-questions/{id}` |  |

## super::service-changes

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/cancellations` |  |
| POST | `/api/v1/admin/cancellations/{id}/decide` |  |
| DELETE | `/api/v1/admin/services/{id}/change` |  |
| POST | `/api/v1/admin/services/{id}/change` |  |
| GET | `/api/v1/admin/services/{id}/lifecycle` |  |
| DELETE | `/api/v1/client/services/{id}/cancellation` |  |
| POST | `/api/v1/client/services/{id}/cancellation` |  |
| DELETE | `/api/v1/client/services/{id}/change` |  |
| POST | `/api/v1/client/services/{id}/change` |  |
| GET | `/api/v1/client/services/{id}/lifecycle` |  |

## super::settings

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/settings/bank-transfer` |  |
| PUT | `/api/v1/admin/settings/bank-transfer` |  |

## super::setup-wizard

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/setup-wizard` |  |
| PUT | `/api/v1/admin/setup-wizard/dismissed` |  |

## super::smtp

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/settings/smtp` |  |
| PUT | `/api/v1/admin/settings/smtp` |  |
| POST | `/api/v1/admin/settings/smtp/test` | Send a test mail synchronously with the *saved* settings. |

## super::ssl

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/domains/{id}/ssl-check` |  |
| GET | `/api/v1/admin/ssl` |  |
| GET | `/api/v1/client/ssl` |  |

## super::sso

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/client/services/{id}/sso` |  |
| POST | `/api/v1/sso/consume` | Called by the panel. 200 with the claims the first time; 401 otherwise. |

## super::staff

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/roles` |  |
| POST | `/api/v1/admin/roles` |  |
| DELETE | `/api/v1/admin/roles/{id}` |  |
| PUT | `/api/v1/admin/roles/{id}` |  |
| GET | `/api/v1/admin/security/staff-2fa` |  |
| PUT | `/api/v1/admin/security/staff-2fa` | Turning the policy on requires the actor to have 2FA (no self lock-out). |
| GET | `/api/v1/admin/staff` |  |
| PUT | `/api/v1/admin/users/{id}/roles` |  |

## super::store

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/customers/{id}/subaccounts` | Staff view of an account's sub-accounts (WHMCS "Users" tab). |
| POST | `/api/v1/admin/orders` | Manual order for a customer, priced from the catalog like a client order. |
| POST | `/api/v1/admin/orders/{id}/notes` |  |
| POST | `/api/v1/admin/orders/{id}/refund` | Refund an order: credit the paid invoice in full (credit note) and close |
| GET | `/api/v1/client/access` |  |
| POST | `/api/v1/client/checkout` | Turn a cart into an order + invoice for the signed-in customer. The |
| GET | `/api/v1/client/email-preferences` |  |
| PUT | `/api/v1/client/email-preferences` |  |
| GET | `/api/v1/client/home` |  |
| GET | `/api/v1/client/login-history` | The caller's own recent sign-ins, failures and lockouts. |
| GET | `/api/v1/client/orders/{id}` | Order status page for the customer. |
| GET | `/api/v1/client/subaccounts` |  |
| POST | `/api/v1/client/subaccounts` | Create a sub-account that signs in with its own email and password and |
| POST | `/api/v1/client/subaccounts/invite` | Invite a contact by email: the account is created with an unusable random |
| DELETE | `/api/v1/client/subaccounts/{id}` | Remove a contact: its access ends immediately (sessions revoked) and |
| PUT | `/api/v1/client/subaccounts/{id}` |  |
| GET | `/api/v1/store/carts/{id}` |  |
| PUT | `/api/v1/store/carts/{id}` | Create or replace a cart. The id is an unguessable client-generated |
| GET | `/api/v1/store/gateways` |  |

## super::support

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/ticket-canned` |  |
| POST | `/api/v1/admin/ticket-canned` |  |
| DELETE | `/api/v1/admin/ticket-canned/{id}` |  |
| PUT | `/api/v1/admin/ticket-canned/{id}` |  |
| GET | `/api/v1/admin/ticket-departments-sla` |  |
| PUT | `/api/v1/admin/ticket-departments/{id}/sla` |  |
| GET | `/api/v1/admin/ticket-escalations` |  |
| POST | `/api/v1/admin/ticket-escalations` |  |
| POST | `/api/v1/admin/ticket-escalations/run` | Enqueue an escalation pass now (durable job; the worker also schedules one |
| DELETE | `/api/v1/admin/ticket-escalations/{id}` |  |
| PUT | `/api/v1/admin/ticket-escalations/{id}` |  |
| GET | `/api/v1/admin/ticket-satisfaction` | CSAT report: distribution, per department / staff, recent comments. |
| GET | `/api/v1/admin/ticket-sla` |  |
| GET | `/api/v1/admin/ticket-staff` |  |
| POST | `/api/v1/admin/tickets/{id}/merge` |  |
| POST | `/api/v1/admin/tickets/{id}/split` |  |
| PUT | `/api/v1/admin/tickets/{id}/tags` |  |
| POST | `/api/v1/client/tickets/{id}/rate` |  |

## super::tax

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/customers/{id}/vat/verify` |  |
| GET | `/api/v1/admin/settings/tax` |  |
| PUT | `/api/v1/admin/settings/tax` |  |
| GET | `/api/v1/admin/tax-rules` |  |
| POST | `/api/v1/admin/tax-rules` |  |
| DELETE | `/api/v1/admin/tax-rules/{id}` |  |
| PUT | `/api/v1/admin/tax-rules/{id}` |  |
| POST | `/api/v1/client/vat/verify` |  |

## super::ticket-attachments

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/tickets/{tid}/attachments/{id}` |  |
| GET | `/api/v1/client/tickets/{tid}/attachments/{id}` |  |
| POST | `/api/v1/tickets/attachments` | Upload a file (raw body). Returns an id to pass as `attachment_ids` when |

## super::ticket-statuses

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/ticket-statuses` |  |
| DELETE | `/api/v1/admin/ticket-statuses/{slug}` |  |
| PUT | `/api/v1/admin/ticket-statuses/{slug}` |  |
| GET | `/api/v1/ticket-statuses` |  |

## super::tickets

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/ticket-departments` |  |
| POST | `/api/v1/admin/ticket-departments` |  |
| PUT | `/api/v1/admin/ticket-departments/{id}` |  |
| GET | `/api/v1/admin/tickets` |  |
| POST | `/api/v1/admin/tickets` |  |
| GET | `/api/v1/admin/tickets/{id}` |  |
| PATCH | `/api/v1/admin/tickets/{id}` |  |
| DELETE | `/api/v1/admin/tickets/{id}/messages/{mid}` |  |
| PUT | `/api/v1/admin/tickets/{id}/messages/{mid}` |  |
| POST | `/api/v1/admin/tickets/{id}/reply` |  |
| GET | `/api/v1/client/ticket-departments` |  |
| GET | `/api/v1/client/tickets` |  |
| POST | `/api/v1/client/tickets` |  |
| GET | `/api/v1/client/tickets/{id}` |  |
| POST | `/api/v1/client/tickets/{id}/close` |  |
| POST | `/api/v1/client/tickets/{id}/reply` |  |

## super::usage

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/services/{id}/usage` |  |
| POST | `/api/v1/admin/services/{id}/usage` |  |
| GET | `/api/v1/admin/usage-metrics` |  |
| POST | `/api/v1/admin/usage-metrics` |  |
| DELETE | `/api/v1/admin/usage-metrics/{id}` |  |
| PUT | `/api/v1/admin/usage-metrics/{id}` |  |
| POST | `/api/v1/admin/usage/bill` |  |
| POST | `/api/v1/admin/usage/sample` |  |
| GET | `/api/v1/client/services/{id}/usage` |  |

## super::vendor

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/servers/{id}/vendor-catalog/sync` | Pull the vendor catalog through the server's module. |
| GET | `/api/v1/admin/vendor-catalog` |  |
| POST | `/api/v1/admin/vendor-catalog/{id}/import` |  |
| PUT | `/api/v1/admin/vendor-catalog/{id}/markup` |  |

## super::webhooks

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/webhooks/{gateway}` |  |

## support

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/support/departments` | departments (registered route) |
| PUT | `/api/v1/admin/support/departments/{id}` | update department (registered route) |
| POST | `/api/v1/admin/support/departments/{id}/pipe` | pipe now (registered route) |
| GET | `/api/v1/admin/support/spam-rules` | spam rules (registered route) |
| POST | `/api/v1/admin/support/spam-rules` | add spam (registered route) |
| DELETE | `/api/v1/admin/support/spam-rules/{id}` | del spam (registered route) |

## themes

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/themes/{id}/assets/{*file}` | theme asset (registered route) |

## tickets

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/tickets/{id}/time` | time list (registered route) |
| POST | `/api/v1/admin/tickets/{id}/time` | time add (registered route) |
| DELETE | `/api/v1/admin/tickets/{id}/time/{entry}` | time del (registered route) |
| GET | `/api/v1/admin/tickets/{id}/watchers` | get watchers (registered route) |
| PUT | `/api/v1/admin/tickets/{id}/watchers` | put watchers (registered route) |

## tlds

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/tlds/bulk-adjust` | admin tld adjust (registered route) |
| POST | `/api/v1/admin/tlds/copy-currency` | admin tld copy (registered route) |

## translations

| Method | Path | Summary |
|---|---|---|
| DELETE | `/api/v1/admin/translations` |  |
| GET | `/api/v1/admin/translations` |  |
| PUT | `/api/v1/admin/translations` |  |

## trusted-proxy

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/security/trusted-proxies` |  |
| PUT | `/api/v1/admin/security/trusted-proxies` |  |

## updates

| Method | Path | Summary |
|---|---|---|
| GET | `/api/v1/admin/system/updates` |  |
| PUT | `/api/v1/admin/system/updates` |  |
| POST | `/api/v1/admin/system/updates/check` |  |

## users

| Method | Path | Summary |
|---|---|---|
| POST | `/api/v1/admin/users/{id}/login-as` | login as user (registered route) |

