API Documentation: data-mutate and data-create

Prev Next

Introduction

This document explains how the data-create and data-mutate APIs in DAZZM work, allowing interaction with data in the DAZZM database.

Unlike a traditional REST approach, which modifies a resource by providing a complete new version, DAZZM's API relies on specific named commands. For example, an aggregate may offer commands such as "create", "updateIdentification", "updateAddress", "deactivate", and "delete". This architecture, inspired by Domain-Driven Design, CQRS, and Event Sourcing, enables granular control over operations, allowing targeted modifications to a resource. Each command generates a domain event, ensuring detailed traceability of changes and precise tracking of actions within the system.

This approach also enhances system integrity by enforcing strictly defined commands and parameters, reducing errors and data inconsistencies. Each aggregate can be seen as a microservice with its own dedicated APIs.

To modify a specific field, you must identify the appropriate command and provide the necessary parameters.

Note for the examples

The examples in this document use the "User" model, an aggregate present in all DAZZM applications.

Creating an Aggregate with "data-create"

To create an aggregate, invoke the data-create service, specifying the exact name of the creation command, the type identifier, and the required parameters.

Request and Response Structure

Structure of a query with fetch

Here is an example to create a user with the command named "create":

fetch('https://votre_environement.api.octopus-esm.com/prod/data-create', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'api-key': 'votre_token'
  },
  body: JSON.stringify({
    "typeId":"776e839a-6e1c-42b9-8efd-8b6db21b4797", 
    "commandName":"create",  
    "commandArgs":{
        "firstName":"Michel", 
        "lastName":"Roberge", 
        "email":"mr@ici.com", 
        "language":"fr"}
    })
})
  .then(response => response.json())
  .then(body => console.log(body))
  .catch(error => console.error(error));

Notice the word "create" in two places. The first is "data-create" in the URL. This is static and never changes, it is the name of the creation endpoint. The second is in the body of the request ("commandName":"create") and this one can change, for example in an application whose data model is in French, we could indicate "create". Each application has a different data model and command names.

Server Response Structure

Notice that the return value is in JSON format and always contains two elements. The first one, named "event" contains the transaction itself, while "data" contains the newly created data, including the default values ​​that were applied by the system. We see in this example that isActive was initialized to "true" by the "create" command.

{
    "event": {
        "type": "USER_CREATED",
        "aggregateTypename": "User",
        "data": {
            "firstName": "Michel",
            "lastName": "Roberge",
            "email": "mr@ici.com",
            "isActive": true,
            "language": "fr",
            "id": "88f1525c-d105-47b9-a5e4-5e54ac3562b4"
        },
        "aggregateId": "88f1525c-d105-47b9-a5e4-5e54ac3562b4",
        "aggregateVersion": 1,
        "created": 1730757148637,
        "requestId": "ad22d17c-f92e-447d-912b-ad9eb6b28e01",
        "dbId": "999999999",
        "appId": "999999999",
        "appVersion": "dev",
        "userId": "user"
    },
    "data": {
        "_typename": "User",
        "_version": 1,
        "firstName": "Michel",
        "lastName": "Roberge",
        "email": "mr@ici.com",
        "isActive": true,
        "language": "fr",
        "id": "88f1525c-d105-47b9-a5e4-5e54ac3562b4"
    }
}

Modifying an aggregate with "data-mutate"

To modify an existing aggregate, we must invoke the "data-mutate" service by passing as parameters the exact name of the modification command, the identifier of the record to modify, as well as the parameters that this command requests.

Queries and responses

Structure of a query with fetch

Here is an example to modify a user with the command named "updateIdentification".

fetch('https://votre_environement.api.octopus-esm.com/prod/data-mutate, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'api-key': 'votre_token'
  },
  body: JSON.stringify({
    "typeId":"776e839a-6e1c-42b9-8efd-8b6db21b4797", 
    "commandName":"updateIdentification",  
    "id": "88f1525c-d105-47b9-a5e4-5e54ac3562b4",
    "commandArgs":{
        "firstName":"Michel", 
        "lastName":"Roberge", 
        "email":"mr@ici.com"}
    })
})
  .then(response => response.json())
  .then(body => console.log(body))
  .catch(error => console.error(error));

Server Response Structure

Note that the return value is in JSON format and always contains two elements. The first one, named "event" contains the transaction itself, while "data" contains the modified data.

{
    "event": {
        "type": "USER_IDENTIFICATION_UPDATED",
        "data": {
            "firstName": "Michel",
            "lastName": "Dupuis",
            "email": "mr@ici.com"
        },
        "aggregateId": "88f1525c-d105-47b9-a5e4-5e54ac3562b4",
        "aggregateTypename": "User",
        "aggregateVersion": 2,
        "created": 1730757965432,
        "requestId": "e1618d64-6c6b-4e27-8ef5-f18a57505191",
        "previousData": {
            "lastName": "Roberge"
        },
        "dbId": "99999999",
        "appId": "99999999",
        "appVersion": "dev",
        "userId": "user"
    },
    "data": {
        "isActive": true,
        "_version": 2,
        "lastName": "Dupuis",
        "_typename": "User",
        "email": "mr@ici.com",
        "id": "88f1525c-d105-47b9-a5e4-5e54ac3562b4",
        "firstName": "Michel",
        "language": "fr"
    }
}