Javascript client

    If you're familiar with Javascript/TypeScript, you can make use of our official client to perform requests to the Content Management API.

    It offers a number of benefits over making raw requests yourself:

    How to install the client

    Depending on the environment you're working (browser or NodeJS), you can install one of these two packages:

    npm install @datocms/cma-client-browser
    npm install @datocms/cma-client-node

    They both offer the same functionality. The only difference between the two, is in the methods available to upload files and create assets in your project, which are optimized for the different environment.

    Initializing the client

    You can use the buildClient function to initialize a new client.

    import { buildClient } from '@datocms/cma-client-node';
    const client = buildClient({ apiToken: '<YOUR_TOKEN>' });
    Specifying a sandbox environment

    By default, every API request you perform will point to the current primary environment, but if you want to make changes to a specific sandbox environment, you can pass it in the initialization options:

    import { buildClient } from '@datocms/cma-client-node';
    const client = buildClient({
    apiToken: '<YOUR_TOKEN>',
    environment: 'my-sandbox-environment',
    });
    Logging request/responses

    The client can output logs of the API request and responses it performs to help you debug issues with your code. You can choose different level of logging, depending on how much information you need:

    import { buildClient, LogLevel } from '@datocms/cma-client-node';
    const client = buildClient({
    apiToken: '<YOUR_TOKEN>',
    logLevel: LogLevel.BASIC,
    });

    The different levels of logging available are:

    • LogLevel.NONE (the default level): No output is generated;

    • LogLevel.BASIC: Logs HTTP requests (method, URL) and responses (status);

    • LogLevel.BODY: Logs HTTP requests (method, URL, body) and responses (status, body);

    • LogLevel.BODY_AND_HEADERS: Logs HTTP requests (method, URL, headers, body) and responses (status, headers, body).

    Raw vs Simplified endpoint methods

    The client is organized by type of resource. For every resource, it offers a number of async methods to perform a CRUD request to a specific endpoint of the API:

    // Example: Item Type (Model)
    await client.itemType.rawList(...);
    await client.itemType.rawFind(...);
    await client.itemType.rawCreate(...);
    await client.itemType.rawUpdate(...);
    await client.itemType.rawDestroy(...);

    "Why the raw prefix on all the methods?" you might ask. Well, let's take a closer look at one specific method call — in this case, the update of an existing model.

    As already covered in previous sections, the API follows the JSON:API convention, which requires a specific format for the payloads. Every request/response has a data attribute, which contains a number of Resource Objects, which in turn contain different of top-level members (id, type, attributes, relationships, meta, etc), each with their own semantic:

    const response = await client.itemTypes.rawUpdate('34532432', {
    data: {
    id: '34532432',
    type: 'item_type',
    attributes: {
    name: 'Article',
    api_key: 'article',
    },
    relationships: {
    title_field: { data: { id: '451235', type: 'field' } },
    },
    }
    });
    console.log(`Created model ${response.data.attributes.name}!`);

    As you can see from the example above, it can become very verbose to write even simple code using this format! That's why the client also offers a "simplified" method for every endpoint — without the raw prefix — which greatly reduces the amount of boilerplate code required:

    const itemType = await client.itemTypes.update('34532432', {
    name: 'Article',
    api_key: 'article',
    title_field: { id: '451235', type: 'field' },
    });
    console.log(`Created model ${itemType.name}!`);

    So the complete set of methods available for the Model resource is:

    // Example: Item Type (Model)
    await client.itemType.list(...);
    await client.itemType.rawList(...);
    await client.itemType.find(...);
    await client.itemType.rawFind(...);
    await client.itemType.create(...);
    await client.itemType.rawCreate(...);
    await client.itemType.update(...);
    await client.itemType.rawUpdate(...);
    await client.itemType.destroy(...);
    await client.itemType.rawDestroy(...);

    In the next sections, you'll find a real-world usage example of the client for every endpoint offered by the API.

    Error management

    In case an API call fails with HTTP status code outside of the 2xx range, an ApiError exception will be raised by the client, containing all the details of the request/response.

    import { ApiError } from '@datocms/cma-client-node';
    try {
    await client.itemType.create({
    name: 'Article',
    api_key: 'article',
    });
    } catch(e) {
    if (e instanceof ApiError) {
    // Information about the failed request
    console.log(e.request.url);
    console.log(e.request.method);
    console.log(e.request.headers);
    console.log(e.request.body);
    // Information about the response
    console.log(e.response.status);
    console.log(e.response.statusText);
    console.log(e.response.headers);
    console.log(e.response.body);
    } else {
    throw e;
    }
    }

    The error object also includes a .findError() method that you can use to check if the response includes a particular error code:

    // finds in the array of api_error entities an error with code 'INVALID_FIELD',
    // that in its details has the key 'field' set to 'api_key':
    const errorEntity = e.findError('INVALID_FIELD', { field: 'api_key' });

    Ponyfilling fetch()

    If your Javascript environment does not provide the Fetch API interface — for example, if you are using a version of Node lower than 18 — you will need to specify a ponyfill during client configuration:

    import { buildClient } from '@datocms/cma-client-node';
    import { fetch } from '@whatwg-node/fetch';
    const client = buildClient({ apiToken: '<YOUR_TOKEN>', fetchFn: fetch });