Example API call code

Helpful to get to know the API is (after you got access), depending on your preference, the insomnia plugin for goTom API

Here we list example implementations using

  • Javascript
  • PHP
  • Bash Script

Example using Javascript with node

Example script, call it callapi.js

#!/usr/bin/env node

const crypto = require('crypto');
const https = require('https');
const url = require('url');

function getRequestUriPart(urlString) {
    const parsedUrl = new URL(urlString);
    return parsedUrl.pathname + parsedUrl.search;
}

function getHostPart(urlString) {
    const parsedUrl = new URL(urlString);
    return `${parsedUrl.protocol}//${parsedUrl.host}`;
}

if (process.argv.length < 4) {
    console.log(`Usage: ${process.argv[1]} <request method> <URL> <user> <secret>`);
    console.log();
    console.log("Note: if you use any other request method than GET you have to provide a request body to stdin");
    process.exit(2);
}

const [, , method, urlString, user, secret] = process.argv;

const host = getHostPart(urlString);
const uri = getRequestUriPart(urlString);

const provider = 'gotom_app_api';
const date = new Date().toISOString().replace(/\.\d{3}/, '');

function processRequest(content) {
    const contentHash = crypto.createHash('md5').update(content).digest('hex');
    const contentType = 'application/json';
    const customHeaders = '';

    const digestParts = `${method.toUpperCase()}\n${contentHash}\n${contentType.toLowerCase()}\n${date}\n${customHeaders}\n${uri}`;
    const digest = crypto.createHmac('sha1', secret).update(digestParts).digest('base64');
    const signature = digest;

    const options = {
        method: method,
        headers: {
            'Authorization': `${provider} ${user}:${signature}`,
            'Content-Type': contentType,
            'Date': date
        }
    };

    const req = https.request(urlString, options, (res) => {
        console.log(`HTTP/${res.httpVersion} ${res.statusCode} ${res.statusMessage}`);
        Object.entries(res.headers).forEach(([key, value]) => {
            console.log(`${key}: ${value}`);
        });
        console.log();

        res.setEncoding('utf8');
        res.on('data', (chunk) => {
            process.stdout.write(chunk);
        });
    });

    req.on('error', (e) => {
        console.error(`problem with request: ${e.message}`);
    });

    if (content) {
        req.write(content);
    }
    req.end();
}

if (method.toUpperCase() === 'GET') {
    processRequest('');
} else {
    let content = '';
    process.stdin.setEncoding('utf8');
    process.stdin.on('readable', () => {
        let chunk;
        while ((chunk = process.stdin.read()) !== null) {
            content += chunk;
        }
    });

    process.stdin.on('end', () => {
        processRequest(content);
    });

    // Set a timeout to end stdin if no input is provided
    setTimeout(() => {
        process.stdin.push(null);
    }, 100);

    process.stdin.resume();
}

From command Line call it for example for a campaign update POST

echo '{"name": "new campaign name", "status": "booking", "bookingDate": "2021-06-23", "note": "new note", "noteInternal": "new note-internal", "noteReservation": "new note-reservation", "campaignTypeId": 3, "campaignTypeReference": "Campaign-Type-Reference 3"}' | node callapi.js POST "https://demo.gotom.io/app-api/campaign/12345" 'theusernameyoureceived' 'thepasswordyoureceived'

Example response

HTTP/1.1 204 No Content
server: nginx/1.26.2
cache-control: no-cache, private
date: Thu, 07 Nov 2024 10:21:15 GMT
connection: close

Example using PHP

<?php

$globalVars = get_defined_vars();
$host = 'https://test-demo.gotom.io'; // Replace demo with your subdomain (optional: replace "test-" for using the production system)
$uri = '/app-api/crm-sync-import-external-crm-id/update-customer';

$provider = 'gotom_app_api';
$user = 'crm_sync_import';
$secret = 'GET_YOUR_SECRET_FROM_GOTOM_SUPPORT'; // replace by XXX before committing!

// $args and $echo controls if the downloaded content should also be written to stdout, otherwise only a file will be created
$args = getopt('', ['echo']);
$echo = isset($args['echo']);

$date = (new DateTime())->format('c');
$method = 'POST';
$content = file_get_contents(__DIR__.'/customer-example-requests/customer.json');
$contentType = 'application/json';
$customHeaders = '';

$digestParts = [
    strtoupper($method),
    $md5content = md5($content),
    strtolower($contentType),
    $date,
    $customHeaders,
    $uri,
];

$digest = hash_hmac('sha1', implode("\n", $digestParts), $secret, true);
$signature = base64_encode($digest);

$headers = [
    'Authorization: '.$provider.' '.$user.':'.$signature,
    'Content-Type: '.$contentType,
    'Date: '.$date,
];

$options = [
    'http' => [
        'method' => $method,
        'header' => implode("\r\n", $headers),
        'content' => $content,
        'ignore_errors' => true,
    ],
];

$currentVars = array_diff_key(get_defined_vars(), $globalVars);
unset($currentVars['digest'], $currentVars['secret'], $currentVars['globalVars']);
file_put_contents(__DIR__.'/variables.json', json_encode($currentVars, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT));

$context = stream_context_create($options);

$bufferLength = 1024 ** 2 * 8; // 8 Mebibyte

// $args and $echo controls if the downloaded content should also be written to stdout, otherwise only a file will be created
$args = getopt('', ['echo']);
$echo = isset($args['echo']);

file_put_contents(__DIR__.'/response.json', '');
$handle = fopen($host.$uri, 'rb', null, $context);
while (!feof($handle)) {
    $buffer = fread($handle, $bufferLength);
    file_put_contents(__DIR__.'/response.json', $buffer, FILE_APPEND);
    if ($echo) {
        echo $buffer;
    }
}

Example using Linux Bash

Store this as callapiendpoint.sh

#!/usr/bin/env bash

function get_request_uri_part() {
  local url="$1"
  echo "/${url#*://*/}"
}

function get_host_part() {
  local url="$1"
  local uri_part
  uri_part="$(get_request_uri_part "$url")"
  echo "${url%"$uri_part"}"
}

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: $0 <request method> <URL> <user> <secret>"
  echo
  echo "Note: if you use any other request method than GET you have to provide a request body to stdin"
  exit 2
fi

url="$2"
host="$(get_host_part "$url")"
uri="$(get_request_uri_part "$url")"

provider='gotom_app_api'
user=${3}
secret=${4}

date=$(date +"%FT%T%:z")
method="$1"
if ! [ -t 0 ]; then content="$(cat)"; else content=""; fi

contentHash=$(echo -n "$content" | md5sum | cut -f1 -d' ')
contentType='application/json'
customHeaders=''

digestParts="${method^^}\n${contentHash}\n${contentType,,}\n${date}\n${customHeaders}\n${uri}"
digest=$(echo -en "$digestParts" | \
    openssl dgst -sha1  -hmac "$secret" -binary | base64)
signature=$digest

curl -i -s "$host$uri" \
    -X "$method" \
    --header "Authorization: $provider $user:$signature" \
    --header "Content-Type: $contentType" \
    --header "Date: $date" \
    -d "$content"



GET example call via Bash script

bash callapiendpoint.sh GET "https://demo.gotom.io/app-api/campaign/26106" 'theuseryoureceived' 'thepasswordyoureceived'

Example response

The response indicates in this case, that it cannot find campaign with externalId 26106 so most likely a wrong externalId was passed to the script

HTTP/1.1 404 Not Found
server: nginx/1.26.2
content-type: application/json
vary: Accept
cache-control: no-cache, private
date: Thu, 07 Nov 2024 09:04:09 GMT
transfer-encoding: chunked

Response body

{
  "type": "https://tools.ietf.org/html/rfc2616#section-10",
  "title": "An error occurred",
  "status": 404,
  "detail": "Not Found"
}

POST JSON example call via Bash script

cat theexamplefileyoucreated.json | bash api-wrapper.sh POST "https://demo.gotom.io/app-api/campaign/26106" 'theuseryoureceived' 'thepasswordyoureceived'