Back
Reseller & API

Webhooks (events and X-Victus-Signature HMAC verification)

Register a webhook endpoint with PUT /webhooks, receive service and billing events, and verify every delivery with the X-Victus-Signature HMAC header.

webhookseventshmacsignatureverification

Because provisioning and lifecycle actions are asynchronous, webhooks are the reliable way to react to state changes without polling. Victus POSTs a JSON event to your URL whenever something happens to your services or balance.

Register your endpoint

bash
# See current webhook config
curl https://control.victuscloud.com/api/reseller/v1/webhooks \
  -H "Authorization: Bearer $VICTUS_KEY"

# Set (or update) the delivery URL and subscribed events
curl -X PUT https://control.victuscloud.com/api/reseller/v1/webhooks \
  -H "Authorization: Bearer $VICTUS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourstore.com/hooks/victus",
    "events": ["service.ready", "service.suspended", "account.low_balance"]
  }'

Save the signing secret

When you set a webhook, the response includes a signing secret (shown once). Store it securely — you need it to verify every incoming delivery via the X-Victus-Signature header.

Events

EventFires when
service.provisioningA create request was accepted and build started.
service.readyA service finished installing and is usable.
service.failedProvisioning or a lifecycle action failed.
service.suspendedA service was suspended (by you or non-payment).
service.unsuspendedA suspended service was restored.
service.terminatedA service was deleted.
service.powerA power state change (start/stop/restart/kill).
backup.completedA backup/snapshot finished.
account.low_balanceYour prepaid credit balance dropped below the threshold.

Verify the signature

Every delivery includes an X-Victus-Signature header: the HMAC-SHA256 of the raw request body keyed with your signing secret, hex-encoded. Compute the same HMAC and compare using a constant-time check. Reject any request that does not match — never trust the payload otherwise.

javascript
const crypto = require('crypto');

function verifyVictus(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody) // the RAW request body, before JSON.parse
    .digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express example (use the raw body, not the parsed one)
app.post('/hooks/victus', express.raw({ type: '*/*' }), (req, res) => {
  const sig = req.header('X-Victus-Signature');
  if (!verifyVictus(req.body, sig, process.env.VICTUS_WEBHOOK_SECRET)) {
    return res.status(400).send('bad signature');
  }
  const event = JSON.parse(req.body.toString('utf8'));
  // handle event.type ...
  res.sendStatus(200);
});

Verify against the raw body

Compute the HMAC over the exact bytes received, before any JSON parsing or re-serialization. Re-encoding the body changes whitespace/key order and breaks the signature check.

Respond fast, process later

Return a 2xx quickly (ideally after signature verification) and do heavy work in a background job. Victus retries deliveries that do not receive a 2xx, so make your handler idempotent using the event id.

Related in Reseller & API

Reseller API overview (sell VPS, game, bot and app hosting under your brand)What the Victus Reseller API is, what you can sell with it, and how the prepaid credit model works so you can build your own storefront on top of Victus infrastructure.Get an API key and understand the prepaid credit modelMint a reseller API key (rslr_...) from the Reseller API page in the Victus panel, store it safely, and top up the prepaid credit balance the API spends.Authentication and base URLThe Reseller API base URL, how to send your rslr_ bearer token, required headers, and a quick authenticated request to confirm your key works.Response format, errors, rate limits and scopesThe standard success {data} and error {errors:[{code,status,detail}]} envelopes, common HTTP status codes, the 240 req/min rate limit, and how key scopes restrict access.List the catalog, plans and regionsRead the available product categories, plans and pricing with GET /catalog, drill into a specific plan code, and list deployment regions with GET /regions.Provision a service (VPS, game, bot and app examples)Create services with POST /services for every category — full curl examples for a VPS, a Minecraft game server, a Discord bot and an app, plus how to poll until it is ready.Manage a service (power, console, usage, lifecycle, backups)Control a provisioned service: power signals, console access, usage stats, suspend/unsuspend, reinstall, resize, reset-password, backups and termination.List services, get a single service, and check your balanceUse GET /services to list everything you have provisioned, GET /services/{id} for one service, GET /account for your credit balance, and GET /account/transactions for the ledger.