HESK API · v1.8.0

Install

The API sits beside HESK 3.7.x. It does not patch or replace HESK PHP files. It reads HESK settings and the HESK database, and can send notification mail through HESK’s own email functions when you ask it to.

Requirements

1. Unpack

unzip hesk-api-1.8.0.zip
sudo mkdir -p /var/www/hesk-api
sudo rsync -a hesk-api-1.8.0/ /var/www/hesk-api/
sudo chown -R www-data:www-data /var/www/hesk-api/storage
sudo chmod -R ug+rwX /var/www/hesk-api/storage

Adjust the web user (www-data, nginx, apache) to match the host.

2. Point the installer at HESK

cd /var/www/hesk-api
sudo -u www-data php bin/install.php \
  --hesk-path=/var/www/hesk \
  --api-url=https://api.help.example.com \
  --create-token --user=admin --name=Bootstrap
FlagMeaning
--hesk-pathDirectory that contains hesk_settings.inc.php
--api-urlPublic URL of this API (no trailing slash)
--hesk-urlPublic HESK URL (defaults to HESK’s own hesk_url)
--api-prefixREST prefix, default /v1
--utf8mb4Optional: convert ticket/reply text columns to utf8mb4 (emoji)
--create-tokenMint a staff token after schema install
--forceOverwrite config/config.local.php

The installer writes config/config.local.php and adds {prefix}api_tokens and {prefix}api_audit_log. {prefix} is whatever HESK already uses (hesk_ by default). Save the bootstrap token when it is printed — it cannot be retrieved later.

3. Web server

Copy deploy/nginx-hesk-api.conf.example, set server_name and root to …/hesk-api/public, enable the site, reload nginx, then issue TLS. The document root must be public/. Do not expose config/, src/, or storage/.

curl -sS https://api.help.example.com/health

You should see "status":"ok" and a version field. Then open /docs (Swagger UI) and /login (staff token portal).

4. Create tokens

Staff sign in at /login with their HESK staff username and password. Each token inherits that user’s categories, privileges, and admin flag.

php bin/create-token.php --user=admin --name="CI"
Authorization: Bearer hsk_…

X-API-Key: hsk_… is also accepted.

Customization

Shipped defaults live in config/config.php. Host overrides go in config/config.local.php (the installer writes this file). Environment variables HESK_PATH, HESK_URL, and HESK_API_URL also override the matching keys.

Paths and URLs

'hesk_path' => '/var/www/hesk',
'hesk_url'  => 'https://help.example.com',
'api_url'   => 'https://api.help.example.com',
'api_prefix'=> '/v1',

api_url is rewritten into the live /openapi.json servers list so Swagger “Try it out” hits this install.

Branding

'branding' => [
    'product_name' => 'HESK API',
    'vendor'       => 'Your Company',
    'vendor_url'   => 'https://example.com',
],

Tokens

'token' => [
    'prefix'           => 'hsk_',
    'secret_bytes'     => 32,
    'default_ttl_days' => null,     // null = never expires
    'max_per_user'     => 20,
],

Rate limits

'rate_limit' => [
    'enabled'        => true,
    'requests'       => 120,
    'window_seconds' => 60,
],

Limits are per token (or per IP before a token is presented).

CORS

'cors' => [
    'allowed_origins' => ['https://app.example.com'],  // or ['*']
    'allowed_methods' => 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
    'allowed_headers' => 'Authorization, Content-Type, X-Requested-With, X-API-Key',
],

Logging, pagination, debug

'log' => [
    'enabled'  => true,
    'path'     => __DIR__ . '/../storage/logs/api.log',
    'log_body' => false,
],
'pagination' => [
    'default_limit' => 25,
    'max_limit'     => 100,
],
'debug' => false,
'timezone' => 'UTC',

Leave debug off in production. Never log Authorization or raw bodies.

Table prefix

Taken from HESK (db_pfix). You do not set it in the API config.

PHP-FPM / nginx

The sample vhost uses unix:/run/php/php8.3-fpm.sock. Change the socket (or use 127.0.0.1:9000) to match the host. Raise fastcgi_read_timeout if you upload large attachments.

Attachments

Size, count, and allowed extensions come from HESK attachment settings. Confirm with GET /v1/attachments/limits. PHP upload_max_filesize and post_max_size also apply.

Time worked

Time tracking is a HESK setting. When it is on, staff tokens with can_reply_tickets or can_edit_tickets can add time:

Accepted values: HH:MM:SS, H:MM:SS, MM:SS, minutes as a number, or {"hours":1,"minutes":30,"seconds":0}. 00:00:00 is ignored. Do not send both fields on the same PATCH.

Message formatting

HESK’s staff UI prints ticket, reply, and note HTML. The API stores message as HTML.

Pipe tables use a header row, a separator with at least three hyphens per column (|---|---|), and body rows separated by real newlines (HESK-stored <br> between rows is also accepted). Alignment: :---, :---:, ---:. Inline markdown in cells is rendered. Keep sending "format": "markdown" — no extra flag.

curl -sS -X POST -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"message":"## Done\n\n- fixed the parser\n- added tests\n\n| Check | Result |\n|---|---|\n| Helpdesk | 200 |","format":"markdown","notify":false}' \
  "$API/v1/tickets/TRACK-ID/replies"

Unicode / emoji

HESK 3.7 ships some text columns as utf8mb3. If ticket create fails on 4-byte UTF-8:

php bin/install.php --hesk-path=… --api-url=… --force --utf8mb4

or apply sql/utf8mb4-message-columns.sql (prefix-aware via the installer).

Apache

Document root = public/. Enable mod_rewrite and:

FallbackResource /index.php

or an equivalent rewrite of all non-files to index.php.

Upgrading

Full procedure (compare versions, checksum, manual replace, notify, auto-install, safety, rollback): Upgrade HESK API →

The updater ships in 1.7.0. Installs on 1.6.0 or older must use the manual steps once; after that you can enable notify or auto-install from the staff portal Updates page.

Manual

  1. Download the zip from this page and confirm the SHA-256.
  2. Unpack next to the old tree.
  3. Copy config/config.local.php (and anything you added under storage/) into the new tree.
  4. Run php bin/install-schema.php — it is safe to re-run (CREATE TABLE IF NOT EXISTS).
  5. Reload PHP-FPM if opcache is on.

Do not overwrite config.local.php with the example file.

Check / notify / auto-install

The package can poll the TDC channel (https://tacticaldataconcepts.com/hesk-api) for a newer version.

php bin/check-updates.php
php bin/check-updates.php --notify
php bin/check-updates.php --apply --confirm=APPLY

REST (admin / can_man_settings):

The staff portal Updates page (/updates) shows this install’s version, the latest TDC version, and a link to upgrade instructions when a newer package exists. The same knobs can be saved there (stored in storage/updates/settings.json, kept across package replace).

'updates' => [
    'enabled' => true,
    'channel_url' => 'https://tacticaldataconcepts.com/hesk-api',
    'mode' => 'off',              // off | notify | auto
    'allow_auto_install' => false, // required for unattended --cron auto-install
    'ticket' => [
        'category' => 1,          // required for notify
        'owner' => 1,             // staff id or username; omit = unassigned
        'priority' => 2,
    ],
],

Cron (example, daily 04:15). mode decides whether the run only checks, opens a ticket, or installs:

15 4 * * * www-data php /var/www/hesk-api/bin/check-updates.php --cron

Safety (all install paths):

The updater prefers version.json on the channel when present. If that file is missing, it uses VERSION plus hesk-api-{version}.zip and hesk-api-{version}.zip.sha256.

Uninstall

Remove the vhost and the API directory. Drop {prefix}api_tokens and {prefix}api_audit_log if you want the database clean. HESK itself is unchanged.