Authentication

Overview

To use any authenticated API, you must first acquire a valid API token.

Crisisworks uses OAuth2 time-limited access tokens, and offers an auth endpoint to fetch the tokens. MFA is supported using TOTP codes.

Crisisworks account & Duty Status

API users must be approved by both Datalink and the Customer of the tenancy, and agree to the API Terms Of Use. If you do not see the API User position, contact Datalink Support to organise these approvals.

API users use the same security system as regular users.

It is recommended your API-enabled user account is only used for the API, as such give it a name like API User.

  • At minimum, this user will require the API User position allocated to it. If you cannot find this position, contact Datalink support.

  • Ensure this user also has the levels of access required to access the data it needs to view or edit for the specific registers.

  • If this API user is going to edit data in registers, the API user MUST BE ON DUTY in the event in one or more positions to have access to read or write data in the registers.

  • If the API user is only updating assets or asset contacts, this data is not in a register, so they don't need to be on duty in any events.

Fetching an authentication token

To fetch an authentication token, call the auth API command and supply the user credentials. Then supply that token to all authenticated API commands using the Authorization header to perform the command on behalf of that user.

Authentication tokens are OAuth2 JWT Access Tokens which expire after a short period. Therefore, for recurring use of the API you should store the username and password securely at your side and call the auth endpoint to fetch a new token.

The API also supports optional TOTP MFA, and you can supply mfaCode at the same time as supplying the username and password. The POSIX authtool utility can be used for this.

To call the auth API, use the following:

POST https://{{host}}/api/json/auth
Accept: application/json
Content-Type: application/json;charset=UTF-8
X-Site: {{site}}

{
  "version": "1",
  "uuid": "{{uuid}}",
  "platform": "Windows",
  "name": "Sync asset contacts",
  "username": "{{username}}",
  "password": "{{password}}",
  "mfaCode": "{{mfaCode}}"
}
Parameter
Type
Mandatory
Description

uuid

string

Yes

A unique code that represents the connected device. For devices this is the device's UUID code. For servers, this should be the server's URL.

platform

string

Yes

A freetext string representing the type of connection — e.g. iPad, iPhone, Windows, Linux

version

string

Yes

The version of the client software — e.g. 11

name

string

Yes

The name of the device or integration — e.g. "Integration X"

username

string

Yes

The user username

password

string

Yes

The user's password

mfaCode

string

No

An optional TOTP MFA code

If the user is successfully authenticated, the command returns a JSON object with the following values:

{
  "status": 200,
  "token": "eyJraWQiOiJCelhSZVwvdW9cL0VUczJjUUJF...",
  "type": "accessToken"
}
Key
Type
Description

token

string

An OAuth2 Access Token which can be used to perform actions on behalf of a nominated user

status

int

200 for success, 400 for invalid intput, 401 for invalid credentials, 500 for internal server errors

type

string

The type of token returned (this will always be 'accessToken')

If the user's credentials are invalid, the server responds with a 401 HTTP error.

{
  "status":401,
  "message":"Invalid user, password or mfaCode"
}

The access token will have a 1 hour expiry, so you will need to re-authenticate for each session.

Using oauthtool for CLI-based MFA

The oauthtool utility is open source software that can be downloaded using your package manager.

  • Debian/Ubuntu: sudo apt install oathtool

  • MacOS: brew install oath-toolkit

  • Windows (WSL or Chocolatey): choco install oath-toolkit

To generate TOTP codes using oathtool, you need the TOTP secret key from Crisisworks. Which can be found by clicking the link "Get code for manual entry" under the QR code when registering the TOTP device.

Next, register the TOTP by entering the following command with your TOTP secret.

oathtool --totp -b "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Each time this is run, this command will return a six-digit TOTP code. You can run it once and enter into Crisisworks to register the tool with Crisisworks for MFA.

Using an authentication token

Once you have acquired the auth token, you can use it for all APIs via the Authorization header as follows.

GET https://{{host}}/api/json/item/id/1
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}

Both Authorization and X-Site are required for most API calls.

Treat your secrets securely

The examples in this guide take shortcuts for readability, with the main one being the storage of secrets in environment variables.

For production use:

  • API users typically have high degrees of access.

  • Treat your API user's password and TOTP secret as sensitive secrets.

  • Don’t hardcode secrets in scripts — use environment variables or secure vault utilities.

For secure storage options, consider using these utilities such as these.

Examples

Authenticating in BASH

The following simple example shows how to call the auth command from a bash script.

# ---- Configuration ----
HOST="api.cw.crisisworks.com"
SITE="sandbox"
UUID="example-uuid-123"
USERNAME="your.username"
PASSWORD="your.password"
CLIENT_NAME="Test Harness"

# ---- Build JSON payload ----
read -r -d '' PAYLOAD <<EOF
{
  "version": "1",
  "uuid": "$UUID",
  "platform": "curl",
  "name": "$CLIENT_NAME",
  "username": "$USERNAME",
  "password": "$PASSWORD"
}
EOF

# ---- Send authentication request and capture response ----
RESPONSE=$(curl -s -X POST "https://${HOST}/api/json/auth" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json;charset=UTF-8" \
  -H "X-Site: ${SITE}" \
  -d "$PAYLOAD")

# ---- Output or process response as needed ----
echo "$RESPONSE"

Authenticating with MFA in BASH

The following shell script illustrates how to authenticate with MFA in bash and curl.

#!/bin/bash

# ---- Configuration ----
HOST="api.cw.crisisworks.com"
SITE="mysite"
UUID="example-uuid-123"
USERNAME="your.username"
PASSWORD="your.password"
TOTP_SECRET="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  # Base32-encoded TOTP secret
CLIENT_NAME="Test Harness"

# ---- Generate current MFA TOTP code using oathtool ----
MFA_CODE=$(oathtool --totp -b "$TOTP_SECRET")

# ---- Build JSON payload ----
read -r -d '' PAYLOAD <<EOF
{
  "version": "1",
  "uuid": "$UUID",
  "platform": "curl",
  "name": "$CLIENT_NAME",
  "username": "$USERNAME",
  "password": "$PASSWORD",
  "mfaCode": "$MFA_CODE"
}
EOF

# ---- Send authentication request and capture response ----
RESPONSE=$(curl -s -X POST "https://${HOST}/api/json/auth" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json;charset=UTF-8" \
  -H "X-Site: ${SITE}" \
  -d "$PAYLOAD")

# --- Extract the token using jq ---
TOKEN=$(echo "$RESPONSE" | jq -r '.token')

# --- Check token was retrieved ---
if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
  echo "❌ Failed to retrieve token."
  exit 1
fi

Now you can call the authenticated commands using the token.

# --- Now make some authenticated API calls ---
RESPONSE=$(curl -s -X GET "https://${HOST}/api/json/ping" \
  -H "Accept: application/json" \
  -H "Authorization: $TOKEN" \
  -H "Content-Type: application/json;charset=UTF-8" \
  -H "X-Site: $SITE")
  
# --- Output the ping response ---
echo $RESPONSE  

Authenticating with MFA in PowerShell

The following example shows how to authenticate in Windows PowerShell.

# --- Configuration ---
$host     = "api.cw.crisisworks.com"
$site     = "mysite"
$uuid     = "example-uuid-123"
$username = "your.username"
$password = "your.password"
$totpSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  # Base32-encoded TOTP secret
$clientName = "Test Harness"

# --- Generate MFA code using oathtool ---
# Ensure oathtool is in PATH (e.g., from Chocolatey or WSL)
$mfaCode = & oathtool --totp -b $totpSecret

# --- Prepare request payload ---
$body = @{
    version  = "1"
    uuid     = $uuid
    platform = "curl"
    name     = $clientName
    username = $username
    password = $password
    mfaCode  = $mfaCode
} | ConvertTo-Json -Depth 3

# --- Send POST request to fetch token ---
$response = Invoke-RestMethod -Method Post `
    -Uri "https://$host/api/json/auth" `
    -Headers @{
        "Accept"       = "application/json"
        "Content-Type" = "application/json;charset=UTF-8"
        "X-Site"       = $site
    } `
    -Body $body

# --- Extract the token from the response ---
$token = $response.token

# --- Verify token and use it ---
if (-not $token) {
    Write-Error "❌ Failed to retrieve token."
    exit 1
}

Now you can call the other API commands using the token.

# --- Call the authenticated /ping endpoint ---
$pingResponse = Invoke-RestMethod -Method Get `
    -Uri "https://$host/api/json/ping" `
    -Headers @{
        "Authorization" = $token
        "Accept"        = "application/json"
        "Content-Type"  = "application/json;charset=UTF-8"
        "X-Site"        = $site
    }

# --- Output the ping response ---
$pingResponse

Authenticating in PHP

// Configuration
$host       = "api.cw.crisisworks.com";
$site       = "mysite";
$uuid       = "example-uuid-123";
$username   = "your.username";
$password   = "your.password";
$totpSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // Base32-encoded TOTP secret
$clientName = "Test Harness";

// Build the payload
$payload = json_encode([
    "version"  => "1",
    "uuid"     => $uuid,
    "platform" => "curl",
    "name"     => $clientName,
    "username" => $username,
    "password" => $password,
    "mfaCode"  => $mfaCode,
]);

// Send the request
[$statusCode, $body] = sendByCurl(
    'POST',
    $url . '/api/json/auth',
    [
        'Accept' => 'application/json',
        'Content-Type' => 'application/json;charset=UTF-8',
    ],
    $payload
);

// Handle the result
if ($statusCode >= 200 && $statusCode < 300) {
    $bodyDecoded = json_decode($body, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception("Could not parse JSON during auth registration");
    }
} else {
    throw new Exception("Got invalid http status code $statusCode during auth registration");
}

if (!($bodyDecoded['token'] ?? null)) {
    throw new Exception("Did not receive an auth token during registration");
}

// Use this token for future authenticated calls
$token = $bodyDecoded['token'];

The above code uses a function to perform the HTTP call

function sendByCurl(string $method, string $url, array $headers, string $payload = null): array
{
    $headersAsStrings = [
        'Content-Length: ' . strlen($payload),
    ];
    foreach ($headers as $key => $val) {
        $headersAsStrings[] = $key . ': ' . $val;
    }

    $ch = curl_init();

    // configuration directives
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // set 30 second timeout on APIs
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 60000);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 60000);

    // set the header, method and payload
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headersAsStrings);
    if (strtoupper((string)$method) === 'GET') {
        // do nothing
    } else {
        if (strtoupper((string)$method) === 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);
        } else {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        }
    }
    if ($payload) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    }

    curl_setopt($ch, CURLOPT_ENCODING, ''); // not gzip, deflate

    // Call the URL
    $body = curl_exec($ch);
    $statusCode = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

    // Test the response to ensure valid json
    if ($statusCode === 200) {
        json_decode($body, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            $statusCode = 400; // invalid response data
        }
    }
    curl_close($ch);

    return [$statusCode, $body];
}

Last updated

Was this helpful?