Skip to content

API Client Implementation in Javascript (Nodejs)

Note: Does not support EspoCRM versions lower than 7.0.0.

Usage

const Client = require('./espocrm-api-client');

const client = new Client(
    'https://your-espocrm-site',
    'API_KEY',
    'SECRET_KEY' // optional, if hmac auth is used
);

// POST example

let payload = {
    name: 'some name'
};

client
    .request('POST', 'Account', payload)
    .then(response => {
        // success
        console.log(response);
    })
    .catch(reresponses => {
        // error
        console.log(response.statusCode, response.statusMessage);
    });

// GET example

let params = {
    maxSize: 5,
    where: [
        {
            type: 'equals',
            attribute: 'type',
            value: 'Customer',
        }
    ],
    select: ['id', name'],
};

client
    .request('GET', 'Account', params)
    .then(response => {
        console.log(response);
    })
    .catch(reresponses => {
        // error
        console.log(response.statusCode, response.statusMessage);
    });

Module

File espocrm-api-client.js:

class Client {

    constructor (url, apiKey, secretKey, options) {
        this.url = url;
        this.apiKey = apiKey;
        this.secretKey = secretKey;

        if (this.url.substr(-1) === '/') {
            this.url = this.url.substr(0, this.url.length -1);
        }

        this.options = options || {};

        this.urlPath = '/api/v1/';
        this.isHttps = url.toLowerCase().indexOf('https') === 0;
    }

    request (method, action, data) {
        method = method || 'GET';
        method = method.toUpperCase();

        let url = this._buildUrl(action);

        let headers = {};

        if (this.apiKey && this.secretKey) {
            let string = method + ' /' + action;

            const crypto = require('crypto');

            let b2 = crypto
                .createHmac('sha256', this.secretKey)
                .update(string)
                .digest();

            let b1 = Buffer.from(this.apiKey + ':');

            let authPart = Buffer.concat([b1, b2]).toString('base64');

            headers['X-Hmac-Authorization'] = authPart;
        }
        else if (this.apiKey) {
            headers['X-Api-Key'] = this.apiKey;
        }
        else {
            throw new Error('Api-Key is not set.');
        }

        let postData;

        if (data) {
            if (method === 'GET') {
                const querystring = require('querystring');

                url += '?' + querystring.stringify({searchParams: JSON.stringify(data)});
            }
            else {
                postData = JSON.stringify(data);

                headers['Content-Type'] = 'application/json';
                headers['Content-Length'] = Buffer.byteLength(postData);
            }
        }

        return new Promise((resolve, reject) => {
            let o = {
                headers: headers,
                method: method,
            };

            if (this.options.port) {
                o.port = this.options.port;
            }

            if (this.options.timeout) {
                o.timeout = this.options.timeout;
            }

            const h = this.isHttps ? require('https') : require('http');

            const req = h.request(url, o, res => {
                let data = '';

                res.on('data', chunk => {
                    data += chunk;
                });

                res.on('end', () => {
                    if (res.statusCode < 200 || res.statusCode > 299) {
                        reject(res);

                        return;
                    }

                    try {
                        data = JSON.parse(data);
                    }
                    catch (e) {
                        console.error(`Error: Could not parse response`);
                        reject({});

                        return;
                    }

                    resolve(data, res);
                });
            });

            req.on('error', e => {
                console.error(`Error: ${e.message}`);
                reject(e);
            });

            if (data && method !== 'GET') {
                req.write(postData);
            }

            req.end();
        });
    }

    _buildUrl (action) {
        return this.url + this.urlPath + action;
    }
}

if (module && module.exports) {
    module.exports = Client;
}