Zum Hauptinhalt springen

Settings, Users and Roles

Settings​

Settings holds your business identity and everything that is about your company rather than about a particular tenant.

Vodia Billing 15 Vodia Billing 16

Business identity​

Your legal name, address, tax registration number, and the contact details printed on every invoice. Also the account reference field, which is the PBX field Vodia Billing matches your customer identifiers against — by default parm1.

Public origin​

The externally reachable origin used to build invoice share links. It must be the address your customers can actually reach, so a link in an invoice email opens rather than failing.

SMTP​

Host, port, encryption, username, password and from-address.

SMTP configured here is stored in the database with the password encrypted under ENCRYPTION_KEY. It is never returned to the browser, and saving with a blank password keeps the stored one.

Resolution is database first, environment second. An existing SMTP_HOST in .env keeps working and can be overridden here without a redeploy; clearing the settings falls back to .env.

A test email button validates the configuration.

With no SMTP configured, email is disabled and the interface says so. Bill runs still prepare and finalize.

Branding and templates​

The invoice template library: logo, colours, footer text and language per template. Thirteen languages are available, with per-key fallback to English.

Assign templates per customer. A customer with no template inherits the default. The template is a property of the document, so it belongs to the party being invoiced rather than to any one of its sites.

Each template can print a link to the customer's portal in the invoice footer. Set it under Settings → Invoice templates → Edit, at the bottom of the dialog.

FieldWhat it does
Portal link on the invoiceOff (default), One link per customer or One link per site
Portal link labelThe words printed before the link. Blank prints "Your portal" in the invoice's language
Portal URL patternThe address to link to, built per customer from the fields below

The pattern can use two fields:

FieldReplaced with
{domain}The site's PBX domain
{account_ref}The account reference, URL-encoded

For example, https://{domain}/ links each site to its own PBX domain, and https://portal.example.com/login?ref={account_ref} links to one portal with the customer's reference.

  • One link per customer builds a single link from the customer's primary site and the customer's account reference.
  • One link per site prints one line per site on a multi-site invoice, labelled with the site name. A single-site customer gets one unlabelled line, and sites that resolve to the same address print once.
  • A site with no account reference of its own uses the customer's. If the pattern needs a value that is missing, no link is printed rather than a broken one.

A customer can carry its own portal link, set under Customers → Invoice address…. When set, it is printed instead of the template's link, once per invoice. With the mode on and the pattern left empty, only customers with their own link get one.

Off means no link prints at all, a customer's own link included.

The pattern must start with http:// or https://. A pattern with an unknown field, such as {domian}, is refused when the template is saved.

The link is printed in the footer with the full address as its text, so a printed or PDF copy still carries it. It is not added to the invoice email.

The link is frozen onto the invoice when it is finalized. Changing the template or the customer's link afterwards does not change an invoice already issued. A draft preview shows the current link.

Seat & object names​

What each counted seat or object is called on invoices: extension types such as ext:resident and ext:agent, and PBX objects such as acds and hunts.

Every key has a built-in name, for example ext:resident is "Resident Extensions" and acds is "Call Queues". Type a name beside any key to replace it across the whole installation; leave it blank to use the built-in name. Back to built-in names removes every name set here.

The name appears on the invoice, the share page and emailed copy, Xero and QuickBooks lines, the per-site sections of a grouped invoice, and the plan editor.

A name set here is the default, not the final word:

  1. A seat row on a sell plan can carry its own Line on invoice text, which takes priority over this card
  2. Otherwise the name set here is used
  3. Otherwise the built-in name

The name is written onto each charge when it is generated. A line not yet on an invoice picks up a rename on the next draft. An invoiced line keeps the words it was issued with, apart from lines issued before names existed: those carry no text of their own and print the current name. Invoices already pushed to Xero or QuickBooks keep the text they were sent with.

The keys themselves never change. They are what snapshots count under and what plans price against; only the words printed beside them do.

Built-in names are English. Names typed here print verbatim, whatever the invoice template's language.

Stripe​

The installation's Stripe credentials, and whether customers who have never been decided about are offered card payment.

The secret key and the webhook signing secret are stored encrypted under ENCRYPTION_KEY and are never returned to the browser. Typing a key arms nothing: only Test connection can mark the connection usable, and changing the key disarms it again. Live or test is read from the key's own prefix and never stored separately.

Full detail, including the webhook endpoint and the events to subscribe to, is in Stripe.

Schedule intervals​

How often the scheduler takes PBX snapshots and syncs payments from the accounting package.

Users​

Users manages team access. Visible to super_admin and admin only.

Each user has an email, a role and a password. New users receive a temporary password, must change it on first login, and must then complete two-factor setup.

Roles​

RoleAccess
super_adminEverything, including Users and the Audit log
adminEverything, including Users and the Audit log
viewerRead-only across the whole application

viewer is enforced at the API, not in the interface. Every write method is refused for a viewer regardless of which endpoint it targets, with authentication endpoints exempted so a viewer can still log in and manage their own 2FA.

A user document with no role at all is treated as not a viewer, so an account created before roles existed does not silently lose access. Only an explicit viewer is restricted.

Cost prices, margin and the Margin tab are partner-only regardless of role, and never appear on a customer-visible surface.

Security​

Security manages your own two-factor authentication and passkeys.

  • TOTP — an authenticator app such as Google Authenticator, Authy or 1Password. Required unless a passkey is registered.
  • Passkeys — WebAuthn credentials: fingerprint, face or hardware key. Multiple passkeys per user, one per device.

Two-factor authentication is mandatory. The first login on an unsecured account routes straight to setup.

Passkeys are bound to the hostname

Passkeys are cryptographically tied to RP_ID, which is set from DOMAIN at install. Move the install to a different hostname and every registered passkey stops working; each user must re-register. TOTP is unaffected.

There is deliberately no email password reset. Root access to the server is the recovery factor. To clear a locked-out user's 2FA:

cd /opt/vodia-billing
docker compose exec mongo mongosh vodia_billing --eval \
'db.users.updateOne({email:"you@example.com"},{$set:{totp_enabled:false},$unset:{totp_secret:"",totp_pending_secret:""}})'

Their next login re-enters forced 2FA setup.

Login attempts are rate-limited per IP, RATE_LIMIT_LOGIN per minute, default 10.

Audit log​

Who did what, and when. Visible to super_admin and admin only — a log readable by everyone it audits is a different product.

Logged events include authentication, user changes, tenant and plan configuration changes, rate sheet commits, tax profile application, invoice finalization and voiding, credit application, share link creation and revocation, accounting connections and pushes, call reclassification, and fraud response actions.

Stripe adds its own: settings saved, connection tested, online payment set per customer, a payment page created for a customer, and every event the webhook acted on — payments recorded, refunds booked, disputes opened and closed, and the ones it refused. The Stripe secret key is never written to an audit row; the mode it implies is.