Skip to main content

Data Model Management

Introduction

While your Data Model and the profile/custom tables that make it are usually created by the Actito Integration experts (in coordination with you), the Actito API allows you to fully manage your tables.

This gives you full autonomy over your data model. For instance, you can retrieve the structure of an existing table to create a new one, you can add new fields to a table or create links between them.

The following use case will show you how to:

  1. Retrieve the structure of an existing custom table
  2. Create a new custom table
  3. Update a custom table
note

Modifying your data model can impact your automated data synchronizations.
Please consider that you might need update them too.
In case of doubt, we advise to contact account manager for the assistance of an Integration & Data Expert.

1. Retrieving the structure of an existing custom table

If you want to copy the structure of an existing custom table (used temporarily for testing, for instance), you can retrieve the structure of all custom tables in an entity with the call

GET /custom-table-structure/v5/entities/{entity}/custom-tables

If you already know the ID of the table, you can retrieve the structure of a single table with the call

GET /custom-table-structure/v5/entities/{entity}/custom-tables/{customTableId}

You will get the JSOn definition of the table as response.

{
"id": "a4aa57cd-64c4-49bc-a17b-34ac8dfa76f8",
"name": "OnlineOrders",
"type": "INTERACTIONS",
"primaryKeyAttribute": "orderId",
"creationTimeAttribute": "orderMoment",
"bigTable": false,
"attributes": [
{
"name": "orderId",
"valueType": "STRING",
"mandatory": true,
"indexed": true,
"unique": true,
"valueRestriction": {
"minLength": 20,
"maxLength": 20
}
},
{
"name": "storeId",
"valueType": "LONG",
"mandatory": true,
"indexed": true,
"unique": false
},
{
"name": "customerId",
"valueType": "LONG",
"mandatory": true,
"indexed": true,
"unique": false
},
{
"name": "orderMoment",
"valueType": "TIMESTAMP",
"mandatory": true,
"indexed": true,
"unique": false
},
{
"name": "amount",
"valueType": "NUMBER",
"mandatory": true,
"indexed": false,
"unique": false
},
{
"name": "status",
"valueType": "STRING",
"mandatory": true,
"indexed": true,
"unique": false,
"valueRestriction": {
"acceptedValues": [
"NEW",
"SHIPPING",
"SHIPPED",
"CANCELED"
]
}
}
],
"foreignKeys": [
{
"name": "link-to-customer",
"attribute": "customerId",
"reference": {
"tableType": "PROFILE_TABLE",
"tableId": "97",
"attribute": "customerId"
},
"onDelete": "CASCADE"
},
{
"name": "link-to-store",
"attribute": "storeId",
"reference": {
"tableType": "CUSTOM_TABLE",
"tableId": "d4d85214-66d4-4072-b98b-a86c9253b980",
"attribute": "storeId"
},
"onDelete": "CASCADE"
}
],
"eventsToTrigger": [
{
"name": "shipped-online-order",
"triggerRules": [
{
"onOperation": "UPDATE",
"onAnyAttribute": [
"status"
],
"matchingConditions": {
"stateBeforeOperation": [
{
"attribute": "status",
"operator": "!=",
"value": "SHIPPED"
}
],
"stateAfterOperation": [
{
"attribute": "status",
"operator": "=",
"value": "SHIPPED"
}
]
}
}
]
}
],
"cleaningRule": {
"type": "OLDEST_RECORDS",
"numberOfRecordsToKeep": 200000
},
"displayOptions": {
"displayName": "Online Orders",
"description": "The table that hosts the orders from an online store. Those orders are linked to the Customers profile table.",
"forAttributes": [
{
"name": "orderId",
"description": "The unique id of the order",
"displayName": "Online Orders ID"
},
{
"name": "storeId",
"description": "The unique id of the online store on which the order has been created.",
"displayName": "Store ID"
},
{
"name": "customerId",
"description": "The unique id of customer who has created the order.",
"displayName": "Customer ID"
},
{
"name": "orderMoment",
"description": "The moment when the order has been created",
"displayName": "Order Moment"
},
{
"name": "amount",
"description": "The amount of the order",
"displayName": "Amount"
},
{
"name": "status",
"description": "The status of the order",
"displayName": "Status"
}
],
"forEvents": [
{
"name": "shipped-online-order",
"displayName": "Shipped Online Order"
}
]
},
"_audit": {
"createdAt": "2019-11-21T08:30:00.000Z",
"updatedAt": "2019-11-21T08:30:00.000Z"
},
"_links": {
"self": {
"href": "/custom-table-structure/v5/entities/MyEntity/custom-tables/69763d8f-2ff2-4fbb-aa9e-8c5ebccb258f"
}
}
}

2. Creating a new custom table

You can use the following call to create a new custom table:

POST /custom-table-structure/v5/entities/{entity}/custom-tables

You can copy the definition of a table you retrieved previously, or build a new table structure using the specs.

tip

If you want to use the definition you retrieved at the previous step to create a new table, you will need to remove the "id", "creationMoment" and "updateMoment" objects from the "attributes" and the "displayOptions" arrays, because these fields are created automatically by Actito.

{
"name": "OnlineOrders",
"type": "INTERACTIONS",
"primaryKeyAttribute": "orderId",
"creationTimeAttribute": "orderMoment",
"compositeKey": null,
"bigTable": false,
"attributes": [
{
"name": "orderId",
"valueType": "STRING",
"mandatory": true,
"indexed": true,
"unique": true,
"valueRestriction": {
"minLength": 20,
"maxLength": 20
}
},
{
"name": "storeId",
"valueType": "LONG",
"mandatory": true,
"indexed": true,
"unique": false,
"valueRestriction": null
},
{
"name": "customerId",
"valueType": "LONG",
"mandatory": true,
"indexed": true,
"unique": false,
"valueRestriction": null
},
{
"name": "orderMoment",
"valueType": "TIMESTAMP",
"mandatory": true,
"indexed": true,
"unique": false,
"valueRestriction": null
},
{
"name": "amount",
"valueType": "NUMBER",
"mandatory": true,
"indexed": false,
"unique": false,
"valueRestriction": null
},
{
"name": "status",
"valueType": "STRING",
"mandatory": true,
"indexed": true,
"unique": false,
"valueRestriction": {
"acceptedValues": [
"NEW",
"SHIPPING",
"SHIPPED",
"CANCELED"
]
}
}
],
"valueAttribute": "amount",
"foreignKeys": [
{
"name": "link-to-customer",
"attribute": "customerId",
"reference": {
"tableType": "PROFILE_TABLE",
"tableId": "97",
"attribute": "customerId"
},
"onDelete": "CASCADE"
},
{
"name": "link-to-store",
"attribute": "storeId",
"reference": {
"tableType": "CUSTOM_TABLE",
"tableId": "d4d85214-66d4-4072-b98b-a86c9253b980",
"attribute": "storeId"
},
"onDelete": "CASCADE"
}
],
"eventsToTrigger": [
{
"name": "shipped-online-order",
"triggerRules": [
{
"onOperation": "UPDATE",
"onAnyAttribute": [
"status"
],
"matchingConditions": {
"stateBeforeOperation": [
{
"attribute": "status",
"operator": "!=",
"value": "SHIPPED"
}
],
"stateAfterOperation": [
{
"attribute": "status",
"operator": "=",
"value": "SHIPPED"
}
]
}
}
]
}
],
"cleaningRule": {
"type": "OLDEST_RECORDS",
"numberOfRecordsToKeep": 200000
},
"displayOptions": {
"displayName": "Online Orders",
"description": "The table that hosts the orders from an online store. Those orders are linked to the Customers profile table.",
"forAttributes": [
{
"name": "orderId",
"description": "The unique id of the order",
"displayName": "Online Orders ID"
},
{
"name": "storeId",
"description": "The unique id of the online store on which the order has been created.",
"displayName": "Store ID"
},
{
"name": "customerId",
"description": "The unique id of customer who has created the order.",
"displayName": "Customer ID"
},
{
"name": "orderMoment",
"description": "The moment when the order has been created",
"displayName": "Order Moment"
},
{
"name": "amount",
"description": "The amount of the order",
"displayName": "Amount"
},
{
"name": "status",
"description": "The status of the order",
"displayName": "Status"
}
],
"forEvents": [
{
"name": "shipped-online-order",
"displayName": "Shipped Online Order"
}
]
}
}

Field value types

Depending on their types, the fields must follow specific constraints:

  • STRING: string of characters [a-z, A-Z, 0-9]

    • the default max number of characters for a STRING type is 255. It can be modified with a "typeValidator" parameter (see table above)
  • LONG:

    • a 64bit integer (no space, dot or comma in number)
    • maximum value: 9223372036854775808
    • minimum value: -9223372036854775808
  • BOOLEAN: match one of the following values “true” or “false”

  • DATE: string of characters matching one of the following formats:

    • YYYYMMDD
    • YYYY-MM-DD
    • dd/MM/yyyy
  • TIMESTAMP: string of characters matching one of the following formats:

    • YYYYMMDD *
    • YYYY-MM-DD *
    • dd/MM/yyyy *
    • YYYYMMDDhhmmss
    • YYYY-MM-DD hh:mm:ss
    • dd/MM/yyyy HH:mm:ss
    • MM/dd/yyyy hh:mm:ss AM|PM
    • If no values are specified for "hhmmss", the values "00:00:00" will be added
  • NUMERIC:

    • separator must be '.'
    • no character amount limit

Creating a table in the UI

Users of the Actito interface can also create new custom table in the "Manage table structure" app.

They can import a JSON file that follows the same structure as in the API.

alt text

tip

The only difference is that they must add an "entityName" parameter to specify the entity on which the new table is created (in the API, the entity name is passed in the path of the call).

{
"name": "ORders24-12-1",
"entityName":"actito",
"type": "INTERACTIONS",
[...]

3. Updating a custom table

A custom table can be updated by applying an operation on the table meta data (change user name, description etc), on existing fields (change user name, data validation etc), or on the table structure (add a relation, index a field, etc).

These updates are called "change requests" and are applied asynchronously. By retrieving the status of a change request, you can check if it was successful.

A change request can be created with the following call:

POST /custom-table-structure/v5/entities/{entity}/custom-tables/{customTableId}/change-requests

The body of the call depends on the type of change request. In the API specs, use the One of tabs to display the relevant documentation.

Add an attribute

Example of JSON body to add a new field to a table:

info

A mandatory attribute cannot be added to an already populated table.

{
"on": "TABLE",
"type": "ADD_ATTRIBUTE",
"attribute": {
"name": "My_New_Attribute",
"valueType": "STRING",
"mandatory": false,
"indexed": false,
"unique": false,
"valueRestriction": {
"maxLength": 30,
"minLength": 0
}
},
"displayOptions": {
"name": "My_New_Attribute",
"displayName": "My New Attribute"
}
}

Delete an attribute

Example of JSON body to delete an attribute from a table:

{
"on": "TABLE",
"type": "REMOVE_ATTRIBUTE",
"attributeName": "My_Old_Attribute"
}

Add a foreign key

Adding a foreign key means linking two tables together (for instance, 2 "Orders" and "Order Lines" Interaction tables, or an Interaction table with a Repository table).

This link is made on an attribute of the source table (the foreign key) that must match a key attribute of the target table.

info

The type of the 2 fields making the link between both table must have the same value type.

{
"on": "TABLE",
"type": "ADD_FOREIGN_KEY",
"foreignKey": {
"name": "link-to-stores-repository",
"attribute": "store",
"reference": {
"tableType": "CUSTOM_TABLE",
"tableId": "1f74f230-9069-4137-8ae6-d2e328721fae",
"attribute": "storeID"
},
"onDelete": "CASCADE",
"integrityCheck": true
}}

Remove a foreign key

Removing a foreign key means deleting the link between 2 tables.

{
"on": "TABLE",
"type": "REMOVE_FOREIGN_KEY",
"name": "link-to-stores-repository"
}

Delete table

This change request will delete the table and all the data stored in it.

danger

This operation is irreversible. Please use with caution.

{
"on": "TABLE",
"type": "DELETE"
}

Make attribute mandatory

This change request will make an attribute mandatory.

info

This operation only works if every single record in the table already have a value for this attribute.
Otherwise, you will first need to create a data import to update existing records with a value.

{
"on": "ATTRIBUTE",
"type": "MAKE_MANDATORY",
"attributeName" : "MyAttribute"
}

Add index on a attribute

This operation will index the target attribute, which will allow users of the interface to make searches on this field and optimize the calculation of targetings.

caution

Max 15 fields can be indexed per table.
Unique and technical fields are indexed by default.
Having too many indexes can slow down performances when creating and updating data.

{
"on": "ATTRIBUTE",
"type": "ADD_INDEX",
"attributeName" : "MyNewIndexedField"
}

Add accepted values for attribute

This operation will add accepted values to an attribute. This only works for attributes that were created with value restrictions.

{
"on": "ATTRIBUTE",
"type": "ADD_ACCEPTED_VALUES",
"attributeName": "MyAttribute",
"acceptedValues" : ["newValue1", "newValue2", "newValue3"]
}

Update table parameters - creationTimeAttribute

By default, the creation time attribute is the technical creationMoment generated by Actito when records are created.

Updating the "creationTimeAttribute" allow you to set your own field (an "OrderMoment", for example) as reference creation moment. It will be used:

  • to sort the order of interactions in the UI
  • to calculate the OLDEST_RECORDS cleaning rule
  • to calculate the recency in the Activation Matrix
{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"creationTimeAttribute": "orderMoment"
}

Update table parameters - valueAttribute

The value attribute sets the monetary value of an interaction. It is used in calculations of the Activation Matrix

info

The value attribute can only be set to INTERACTIONS type tables.
The corresponding attribute must be numeric (NUMBER or LONG).

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"valueAttribute": "amount"
}

Update table parameters - bigTable

This defines whether the table is considered as BIG, which means the maximum number of records is 10 times higher than standard tables, but with some restrictions.

  • Big Interactions tables: Max 100M lines - Max 20 attributes - No STRING attributes allowed
  • Big Linked Data tables: Max 100M lines - Max 20 attributes - No STRING attributes allowed
  • Big Repository tables: Max 100 000 lines - No "recordDisplayExpression" allowed in the display options (STRING allowed)
{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"bigTable: true
}

Update table parameters - eventsToTrigger

Custom Table Events can be triggered when the state of a record changes (create, update, delete) with defined criteria.

These events can be used to trigger specific automations such as starting a Scenario in the UI or pushing a webhook notification.

In the following example, we are creating 2 events:

  • The event named "CREATE" is triggered when a new record is created, without any additional criteria.
  • The event named "offerReady" is triggered when
    • An existing record is updated with the "synchronized" attribute changing from false to true
    • A new record is created with the "synchronized" attribute = true
{
"eventsToTrigger": [
{
"name": "CREATE",
"triggerRules": [
{
"onOperation": "CREATE"
}
]
},
{
"name": "offerReady",
"triggerRules": [
{
"onOperation": "UPDATE",
"onAnyAttribute": [
"synchronized"
],
"onMatchingState": {
"stateBeforeOperation": {
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "synchronized",
"value": false
}
]
},
"stateAfterOperation": {
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "synchronized",
"value": true
}
]
}
}
},
{
"onOperation": "CREATE",
"onMatchingState": {
"stateAfterOperation": {
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "synchronized",
"value": true
}
]
}
}
}
]
}
]
}

Update table parameters - cleaningRules

As custom tables have a max volume, cleaning rules help making room for new records by deleting the data that aren't relevant anymore.

There are two way to define cleaning rules:

  • deleting the oldest records on a FIFO basis
  • deleting records that match a set of criteria

Here is an example of change request to add a FIFO cleaning rule:

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"cleaningRules": {
"oldestRecordsRule": {
"numberOfRecordsToKeep": 2000000
}
}
}

Here is a change request to add a cleaning rule that deletes records whose "status" is "cancelled".

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"cleaningRules": {
"matchingRule": {
"condition": {
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "status",
"value": "CANCELLED"
}
]
}
}
}
}

It is possible to mix both types of conditions:

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"cleaningRules": {
"oldestRecordsRule": {
"numberOfRecordsToKeep": 5000000
},
"matchingRule": {
"condition": {
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "status",
"value": "CANCELLED"
}
]
}
}
}
}

It is also possible to create complex conditions with interlocking criteria. In the example below, a record will be deleted if its "status" is "cancelled" and its "amount" is below 50, or if it was made in the store with id = 2 and the order id is not known.

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"cleaningRules": {
"matchingRule": {
"condition": {
"logicalOperator": "OR",
"conditions": [
{
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "status",
"value": "CANCELED"
},
{
"operator": "<",
"attribute": "amount",
"value": 50.0
}
]
},
{
"logicalOperator": "AND",
"predicates": [
{
"operator": "=",
"attribute": "storeId",
"value": "2"
},
{
"operator": "EMPTY",
"attribute": "orderId"
}
]
}
]
}
}
}
}

Update table parameters - displayOptions

Display options allow you to define the display names and the descriptions of objects such as they will appear to the users of the interface.

This helps defining a clearer picture of the purpose of each object than the technical name might convey.

{
"on": "TABLE",
"type": "UPDATE_PARAMETERS",
"displayOptions": {
"displayName": "Online Orders",
"description": "The table that hosts the orders from an online store. Those orders are linked to the Customers profile table.",
"forAttributes": [
{
"name": "orderId",
"description": "The unique id of the order",
"displayName": "Online Orders ID"
},
{
"name": "storeId",
"description": "The unique id of the online store on which the order has been created.",
"displayName": "Store ID"
},
{
"name": "customerId",
"description": "The unique id of customer who has created the order.",
"displayName": "Customer ID"
},
{
"name": "orderMoment",
"description": "The moment when the order has been created",
"displayName": "Order Moment"
},
{
"name": "amount",
"description": "The amount of the order",
"displayName": "Amount"
},
{
"name": "status",
"description": "The status of the order",
"displayName": "Status"
}
],
"forEvents": [
{
"name": "shipped-online-order",
"displayName": "Shipped Online Order"
}
]
}
}

Updating a custom table from the UI

All the above operation can also be carried in the Actito UI by uploading a JSON file with the same structure in the 'Manage tables structure' app (except the "Delete table" operation which has its own button).

alt text

4. Checking the result of a change request

As change requests are asynchronous, just because the call to create one is in success doesn't mean the operation was carried out successfully. For instance, when creating a change request to make an existing attribute mandatory, the system will asynchronously check that all records already have a value for this attribute.

You can check the result of a change request with the following call:

GET /custom-table-structure/v5/entities/{entity}/custom-tables/{customTableId}/change-requests/{changeRequestId}

The response displays both the content of the change request and its status.

{
"id": "ae808e05-01e7-4299-99cf-f7dc190d5562",
"on": "TABLE",
"type": "ADD_ATTRIBUTE",
"attribute": {
"name": "description",
"valueType": "STRING",
"mandatory": false,
"indexed": false,
"unique": false
},
"status": "SUCCEEDED",
"_audit": {
"createdAt": "2019-11-21T13:00:00.000Z",
"updatedAt": "2019-11-21T13:01:00.000Z"
},
"_links": {
"self": {
"href": "/custom-table-structure/v5/entities/MyEntity/custom-tables/a4aa57cd-64c4-49bc-a17b-34ac8dfa76f8/change-requests/ae808e05-01e7-4299-99cf-f7dc190d5562"
},
"table": {
"href": "/custom-table-structure/v5/entities/MyEntity/custom-tables/a4aa57cd-64c4-49bc-a17b-34ac8dfa76f8"
}
}
}