Example API call code

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'