# API Reference

The TiloRes API is highly customizable. The reference therefore only focusses on the basic and default API.

# mutation: disassemble

The disassemble mutation helps you to remove records and/or edges.

Example request:

mutation {
  disassemble(input: {
    reference: "<uuid>",
    edges: [
      {
        a: "<uuid-record-a>"
        b: "<uuid-record-b>"
      }
    ]
    recordIDs: [
      "<uuid-record-c>"
      "<uuid-record-d>"
    ]
    createConnectionBan: false
    meta: {
      user: "<user-name>"
      reason: "some reason"
    }
  })
}

The reference must be a unique ID, that can be reused if the same request needs to be processed again later due to a previous error.

When providing edges, all edges between the two records will be removed, independent of their type. The records itself will not be removed.

When providing recordIDs, the records as well as their edges will be removed.

You must at least provide one record ID or one edge. You can at the same time provide edges and record IDs. If an edge or a record is the only connecting link between two (or more) parts of an entity, then the entity will be split into multiple entities.

All record IDs mentioned in edges and recordIDs must belong to the same entity.

When an entity was split into multiple entities and the setting createConnectionBan is true (default is false), then this will prevent the newly created entities from ever merging again. Any record that would merge these entities will be dropped in that case. Connection bans will be inherited, meaning, that when entity A, which has a connection ban to entity B, is merged into entity C, then C afterwards also will have a connection ban towards B. The same is true for splitting A.

The user and the reason from the meta block, will currently only show up in the logs and should explain why and when a record or an edge was removed.

Example response:

{
  "deletedEdges": 5,
  "deletedRecords": 2,
  "entityIDs": [
    "A",
    "C"
  ]
}

deletedEdges and deletedRecords represent the number of removed edges and records. deletedEdges may have a higher number than the edges explicitly removed.

entityIDs lists all IDs of the resulting entities. If the disassemble caused the entity to be deleted, this entry will be empty. If the disassemble caused the entity to be updated, it will contain exactly one entry. And otherwise it will contain at least two entries.

If an error occurs during the disassemble, it will first retry it internally again. If this fails again, it will schedule the removal for a later retry and return with an error message to the API user. Usually, the API user can ignore that specific error - it will eventually perform the disassemble.

# mutation: removeConnectionBan

The removeConnectionBan removes an existing connection ban between two or more entities.

Example request:

mutation {
  removeConnectionBan(input: {
    reference: "<uuid>"
    entityID: "<entity-id-a>"
    others: [
      "<entity-id-b>"
      "<entity-id-c>"
    ]
    meta: {
      user: "<user-name>"
      reason: "some reason"
    }
  }) {
    removed
  }
}

The reference must be a unique ID, that can be reused if the same request needs to be processed again later due to a previous error.

The connection ban will always be removed between entityID and each entity ID from others. It will not affect possible connection bans in between the others entities.

The user and the reason from the meta block, will currently only show up in the logs and should explain why and when a record or an edge was removed.

Example response:

{
  "removed": true
}

Unless there was an error, the removed field will always return true.

If an error occurs during the removal, it will first retry it internally again. If this fails again, it will schedule the removal for a later retry and return with an error message to the API user. Usually, the API user can ignore that specific error - it will eventually perform the connection ban removal.

# mutation: submit

The submit mutation adds the provided records into TiloRes.

Example request:

mutation {
  submit(input: {
    records: [
      {
        id: "my-id",
        myCustomField: "some-value"
      }
    ]
  }) {
    recordsAdded
  }
}

The structure for each value in records is dependent on your customized schema for the RecordInput.

Multiple records submitted in a single mutation will be automatically connected with each other using a STATIC edge. This is independent from the matching rules.

Example response:

{
  "recordsAdded": 1
}

recordsAdded will just return the number of records that have successfully be submitted into TiloRes.

# query: entity

The entity query will search for the provided entity ID and return it.

Example request:

{
  entity(input: {
    id: "<uuid-entity>"
  }){
    entity {
      id
      records {
        id
        myCustomField
      }
      edges
      duplicates
      hits
    }
  }
}

The id is the entity ID to search for.

Example response:

{
  "entity": {
    "id": "<uuid-entity>",
    "records": [
      {
        "id": "<record-id-a>",
        "myCustomField": "some value"
      },
      {
        "id": "<record-id-b>",
        "myCustomField": "some other value"
      },
      {
        "id": "<record-id-c>",
        "myCustomField": "some value"
      }
    ],
    "edges": [
      "<record-id-a>:<record-id-b>:STATIC",
      "<record-id-a>:<record-id-b>:R1EXACT"
    ],
    "duplicates": {
      "<record-id-a>": [
        "<record-id-c>"
      ]
    },
    "hits": {}
  }
}

If an entity with the provided ID exists, then this entity will be returned in the entity field. Otherwise this field will be null.

Each entity has the following fields:

id is the entity ID.

records is a list of all records of that entity. The queryable fields depend on the Record from your custom schema.

edges lists all edges in that entity, which represents how the records are connected with each other.

duplicates lists all duplicates of that entry. When not using rule groups the key of that map will be the record ID of the original and the entries will be the record IDs of the duplicates. When using rule groups, the key will additionally be prefixed with the ID of the rule group and a colon (<rule-group-id>:<record-id-a>) and the values stay unchanged. In that case one record ID of a duplicate can be present in the values of multiple keys.

The hits will always be empty for an entity search.

# query: search

The search query will search for the provided values using the search rules.

Example request:

{
  search(input: {
    parameters: {
    	myCustomField: "some-value"
    }
  }) {
    entities {
      id
      records {
        id
        myCustomField
      }
      edges
      duplicates
      hits
    }
  }
}

The parameters define your custom search parameters as they are defined using the SearchParams type.

Example response:

{
  "entities": [
    {
      "id": "<uuid-entity>",
      "records": [
        {
          "id": "<record-id-a>",
          "myCustomField": "some value"
        },
        {
          "id": "<record-id-b>",
          "myCustomField": "some other value"
        },
        {
          "id": "<record-id-c>",
          "myCustomField": "some value"
        }
      ],
      "edges": [
        "<record-id-a>:<record-id-b>:STATIC",
        "<record-id-a>:<record-id-b>:R1EXACT"
      ],
      "duplicates": {
        "<record-id-a>": [
          "<record-id-c>"
        ]
      },
      "hits": {
        "<record-id-a>": [
          "R1EXACT"
        ]
      }
    }
  ]
}

entities is either an empty list or a list with all the found entities. Their structure equals the one described in query: entity, except that for the hits you receive a list of record IDs that fit to the search and the rule ID with which they were found.

# Entity Event Stream

Not yet integrated into the GraphQL API, but also very helpful when it comes to observing changes in entities is the entity event stream. This stream is provided via AWS Kinesis and requires an IAM user to access the data.

Every single data change in TiloRes is published via that stream. The following events are currently available.

# Create Event

The create event will be published, when an entity was newly created, meaning a record was submitted, but could not be attached to an existing entity.

Example:

{
  "type": "CREATE",
  "data": {
    "currentEntityID": "<entity-id>",
    "sourceRecords": [
      {
        "id": "<new-record-id>",
        "data": {
          "myCustomField": "some value"
        }
      }
    ]
  }
}

# Update Event

The update event will be published when a record is submitted and was matched with exactly one existing entity.

Example:

{
  "type": "UPDATE",
  "data": {
    "currentEntityID": "<entity-id>",
    "sourceRecords": [
      {
        "id": "<new-record-id>",
        "data": {
          "myCustomField": "some value"
        }
      }
    ]
  }
}

# Merge Event

The merge event will be published when a record is submitted and was matched with more than one existing entity, resulting in all of these entities being merged.

Example:

{
  "type": "MERGE",
  "data": {
    "currentEntityID": "<entity-id-a>",
    "obsoleteEntityIDs": [
      "<entity-id-b>"
    ],
    "sourceRecords": [
      {
        "id": "<new-record-id>",
        "data": {
          "myCustomField": "some value"
        }
      }
    ]
  }
}

# Split Event

The split event will be published when an edge or a record that connected at least two parts of an entity was deleted, resulting in at least two new entities.

Example:

{
  "type": "SPLIT",
  "data": {
    "obsoleteEntityID": "<entity-id-a>",
    "newEntityIDs": [
      "<entity-id-a>",
      "<entity-id-b>"
    ]
  }
}

# Delete Event

The delete event will be published when all records from an entity have been removed.

Example:

{
  "type": "DELETE",
  "data": {
    "obsoleteEntityID": "<entity-id>"
  }
}