Skip to the guide

Integration keys

An integration key is how other software drives the panel: a billing system creating a website when somebody pays, a script taking a backup before a deployment, a monitoring tool asking what is wrong. This page sets one up, makes a first request with it, and lists every permission you can give it and every limit it enforces.

Before you start

What you need.

  • An owner or administrator account. A customer account cannot make one.
  • A Pro or Business licence in force. Integration keys are the one thing besides the website ceiling that a licence decides, so build against a licensed installation or your requests will be refused with a message saying so.
  • The address you reach the panel on, including the port if it is not the default. Every example below uses https://panel.example.com; substitute yours.

Step 1

Make the key.

In the panel, open Server, then Integrations, then Create an integration key. Fill in the four fields described below, save, and copy the key out of the dialogue before closing it. It is shown once and stored only as a hash; if you lose it, delete it and make another.

A key is recognisable on sight because it begins dashmox_. That prefix is there so one that ends up in a log file, a paste or a repository can be spotted and revoked.

Step 2

Make a request with it.

The key goes in an Authorization header as a bearer token. That is the only place the panel accepts one: a key in a cookie would be sent by a browser automatically, which is the problem the panel's cross-site checks exist to prevent.

curl -s https://panel.example.com/api/v1/sites \
  -H "Authorization: Bearer dashmox_YOUR_KEY_HERE"

That request needs sites.view. A key without it gets back a refusal naming the permission it was missing, which is the quickest way to find out what an integration actually needs:

{"error":"this API token was not given sites.view"}

Creating a website takes a POST and sites.create:

curl -s https://panel.example.com/api/v1/sites \
  -H "Authorization: Bearer dashmox_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jo Smith","domain":"josmith.example.com",
       "runtime":"php","php_version":"8.3"}'

The form

What each field means, and what it refuses.

FieldWhat it is forLimits and refusals
Name How you will recognise this key in the list later. Name it after the thing using it, not after yourself: “WHMCS provisioning” rather than “Jo’s key”. 2 to 60 characters. Shorter or longer is refused.
Permissions Everything this key may do. Nothing else is reachable: a request to a route the key holds no permission for is refused whatever else the key can do. At least one, or the key is refused as useless. Only the names in the table below; anything else is refused rather than stored, so a typo cannot sit in the list looking like a restriction.
Allowed ranges The addresses the key may be used from. A single address or a range both work: 203.0.113.7 for one machine, 203.0.113.0/24 for a subnet. A key fixed to your billing server is useless to anybody who steals it. Up to 20 entries. Leave it empty to allow any address. A single address is stored as a /32, and a range is stored masked, so 203.0.113.7/24 is kept as 203.0.113.0/24.
Expires after Days until the key stops working. An expired key stays in the list, so you can see that it expired rather than wonder where it went. 0 for no expiry, or up to 3650 days. Anything else is refused.

An installation may hold 25 integration keys. The ceiling is there because a list nobody can read through is a list nobody audits.

Permissions

Every name you can give a key.

These are the panel's own permission names, not a separate vocabulary for integrations. A second list of integration-shaped names would need mapping onto this one, and the mapping is the part that comes apart.

AreaPermissionsGive these to
Websites sites.view, sites.create, sites.edit, sites.delete A billing system that provisions and removes hosting.
Files files.view, files.write A deployment script. Note that files.write reaches every website the key can see.
Domains and DNS domains.view, domains.edit, dns.view, dns.manage Anything that adds addon domains or maintains records.
Certificates ssl.view, ssl.manage A tool that supplies its own certificates rather than letting the panel issue them.
Databases databases.view, databases.create, databases.delete An installer that needs a database per application.
Backups backups.view, backups.create, backups.restore, backups.delete A pre-deployment snapshot, or an external retention policy.
Scheduled tasks cron.view, cron.manage An application that installs its own schedule.
Email mail.view, mail.manage Anything creating mailboxes or forwarders.
Logs logs.view A log shipper or an uptime checker reading what a website served.
Accounts customers.manage, users.manage, grants.manage A billing system that creates the customer as well as the hosting.
The server server.view, server.services Monitoring. server.services can restart services, so give it only where that is the point.

The ceiling

What no integration key can do.

A key cannot change how an account signs in. It cannot set a password, cannot alter two-factor, and cannot lock anybody out while it is in use. A stolen key lets somebody do the work you granted rather than take the account, and deleting the key is therefore a complete answer: nothing has been left behind in anybody’s sign-in settings.

Keys reach only routes that were declared with a permission, and a route declared the ordinary way is closed to every key. So a new feature is unreachable by integrations until somebody decides it should be, which is the only direction worth failing in.

Keys belong to the server

Not to the person who made one.

Integration keys sit under Server rather than under an account because they outlive the people who set them up. A billing system should not stop working because somebody left the company, and it should not be able to read every customer’s files merely because the administrator who created the key could.

Earlier versions did offer a key under your own account that acted as you. Those were removed: what they carried was somebody’s whole role, and revoking their sessions did not revoke the key. A key from that era is refused with a message pointing here. If you have one in a script, make an integration key with the permissions that script actually needs.

When something is refused

Reading the error.

What comes backWhat it meansWhat to do
that API token is not valid No key matches. Usually a truncated copy, or one that has been deleted. Check the whole value was copied, including the dashmox_ prefix. If it was deleted, make another.
this API token was not given … The key is valid and lacks the permission that route needs. The message names it. Add that permission, or decide the integration should not be doing it.
that API token is not valid, when you are sure the key is right The key has allowed ranges and the request came from outside them. The panel gives the same answer as it would for an unknown key, on purpose: telling somebody that their stolen key is good and only their address is wrong tells them exactly what to fix. Check which address the panel really saw, below.
integration keys come with a Pro or Business licence… No licence is in force on this installation. Apply a licence. The keys are kept and start working again; nothing needs remaking.
personal tokens were removed… A key from before integration keys existed. Make an integration key and update whatever holds the old one.

Allowed ranges

Which address the check actually uses.

The address matched against your allowed ranges is the one the connection itself came from. Forwarding headers are ignored here, including X-Real-IP, which the activity record does trust. That is deliberate and it matters if you put the panel behind a proxy: a restriction a website hosted on this very server could defeat by setting a header would not be a restriction at all, and every hosted website can connect over loopback.

So if your integration reaches the panel through a reverse proxy, the range to allow is the proxy’s address, not the client’s. If that makes the restriction useless for you, leave the ranges empty and rely on the permissions and the expiry instead.

Afterwards

Seeing what a key did.

Every key records when it was last used, which is how you find one nothing needs any more. What it did is in Operations, then Activity, alongside everything people did, so you can answer what a key did rather than only what it was permitted to do.

Give each integration its own key. Sharing one means revoking it breaks several things at once, and the activity record cannot tell you which of them made a given change.

All guides