NAV navbar

Introducción

URL: https://api.cx.sentisis.io/graphql

¡Bienvenid@ al API de Séntisis Customer eXperience! Aquí encontrarás la documentación necesaria para dar los primeros pasos hacia el análisis programático de tus textos.

Esta API usa graphQL. Para la mayoría de lenguajes existen librerías específicas que facilitan su uso, pero en el fondo no se trata más que de llamadas HTTP al uso con un formato especial en el body. El formato de las respuestas es JSON. GraphQL define unas estructuras de entrada y salida estrictas que conforman el contrato entre cliente y servidor y que llamamos esquema.

Por ejemplo, una llamada básica con curl

curl --request POST \
  --url https://api.cx.sentisis.io/graphql \
  --header 'authorization: Bearer <YOUR_TOKEN>' \
  --data '{"query":"{\n\tallProjects {\n    name\n  }\n}"}'

Seguridad

Cabecera de autenticación

Authorization: Bearer YOUR_TOKEN

La API contará con un certificado SSL para proteger cualquier información confidencial que se envía entre los dos sistemas. La autenticación se realizará mediante la llamada Bearer Token Authentication. Todas las llamadas a la API deberán incluir como cabecera el Bearer Token, que es único por cliente y que puedes encontrar en el Perfil del dashboard de CX.

Mantener en secreto el token de seguridad es responsabilidad del cliente. En el caso de fugas o filtraciones, Séntisis dispone de un método para revocar tokens de acceso.

Errores

Ejemplo de error

{
  "errors": [
    {
      "message": "Dataset not found: fake_dataset_id",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": [
        "project",
        "dataset"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR"
      }
    }
  ],
  # Datos parciales
  "data": {
    "project": {
      "id": "project_id",
      "name": "Proyecto válido",
      "dataset": null
    }
  }
}

Independientemente del código de status HTTP con el que se resuelvan, las operaciones graphQL siempre devuelven un cuerpo JSON. En caso de error, la respuesta contendrá un atributo nuevo, errors, con el listado de errores. Es importante tener en cuenta los siguientes puntos:

La API de Séntisis usa los códigos de error predefinidos de graphQL, que se pueden consultar en el siguiente enlace: https://www.apollographql.com/docs/apollo-server/data/errors/

Para la mayoría de errores la API responderá con un HTTP 200 pero a veces lo hará con un 400 (si la estructura de la petición no se ajusta al esquema) o un 500 (si algo ha ido realmente mal). En todo caso, como hemos dicho, lo importante será revisar el código de error en el body de la respuesta.

Una lista no exhaustiva con algunos ejemplos de errores:

code message HTTP code
GRAPHQL_VALIDATION_FAILED Cannot query field "allProject" on type "Query". Did you mean "allProjects" or "project"? 400
GRAPHQL_VALIDATION_FAILED Expected type Int, found string 400
UNAUTHENTICATED Authentication Error 400
QUOTA_ERROR Quota reached 200
INTERNAL_SERVER_ERROR Dataset not found 200
... ... ...

Arquitectura

La aplicación contará con Proyectos, los cuales contendrán internamente la información sobre cómo se realizará la clasificación de los mensajes (el modelo lingüístico). Por ejemplo, se crearán los proyectos Encuestas, Reclamos y Solicitudes... Dichos proyectos contarán con identificador y un nombre.

Cada proyecto contará con ninguno, uno o varios Datasets. Dichos datasets tendrán un campo identificador, así como campos para el nombre, fecha de creación y estado. El estado indicará si el dataset subido está en el proceso de análisis o listo para ser descargado.

Proyectos

Los proyectos representan modelos de análisis lingüísticos; contienen el conjunto de reglas que se aplicarán a los mensajes recibidos.

Para recibir un listado de los proyectos haremos la petición:

{
  allProjects(first: 10 after: 0) {
    id
    name
    createdAt
  }
}

Petición

Parámetro Tipo Obligatorio Valor por defecto Descripción
first Int no 10 Cantidad de elementos a devolver
after Int no 0 Saltándose este número de elementos

Respuesta

{
  "data": {
    "allProjects": [
      {
        "id": "project_id",
        "name": "Project Name",
        "createdAt": "2020-01-05T11:42:04.314Z"
      },
      …
    ]
  }
}
Atributo Tipo Descripción
id ID! Id del proyecto
name String! Nombre del proyecto
createdAt DateTime! Fecha de creación




{
  project(id: "project_id") {
    id
    name
    createdAt
  }
}
{
  "data": {
    "project": {
      "id": "project_id",
      "name": "Project Name",
      "createdAt": "2020-01-05T11:42:04.314Z"
    }
  }
}

Y para ver los datos de un proyecto en concreto, filtraremos por el id del proyecto usando project en lugar de allProjects

Datasets

Un dataset es una agrupación de mensajes analizados dentro de un determinado proyecto. Estará compuesto por uno o más archivos. De forma similar a los proyectos, podremos pedir un listado paginado de datasets o solamente uno si conocemos su id.

All datasets

Retorna la lista de datasets asociados a un proyecto en específico. Opcionalmente, permite filtrar los resultados de acuerdo a los criterios descritos en el parámetro filters

{
  project(id: "project_id") {
    allDatasets(
      first: 10,
      after: 0,
      filters: {
        attributes: [{ key: "attribute_key_1", value: "attribute_value_1", type: DATASET_ATTRIBUTE }]
      },
    ) {
      id
      name
      createdAt
      status
      attributes {
        key
        value
        type
      }
    }
  }
}

Petición

Parámetro Tipo Obligatorio Valor por defecto Descripción
first Int no 10 Cantidad de elementos a devolver
after Int no 0 Saltándose este número de elementos
filters DatasetFilters no - Filtrados por estos criterios

Respuesta

{
  "data": {
    "project": {
      "allDatasets": [
        {
          "id": "dataset_id",
          "name": "Dataset Name",
          "createdAt": "2020-01-11T11:00:00.000Z",
          "status": "Completed",
          "attributes": [
            {
              "key": "attribute_key_1",
              "value": "attribute_value_1",
              "type": DATASET_ATTRIBUTE,
            }, …
          ],
        }, …
      ]
    }
  }
}
Atributo Tipo Descripción
id ID ID del dataset
name String Nombre del dataset
createdAt DateTime Fecha de la primera subida
status DatasetStatus Estado del dataset: Created, Processing, Completed, Error
attributes [DatasetAttribute] Atributos basados en los tipos: DATASET_ATTRIBUTE, DOCUMENT_COLUMN, BENCHMARK_COLUMN

Specific dataset

También podemos consultar un dataset determinado a través de su ID usando dataset en lugar de allDatasets

{
  project(id: "project_id") {
    dataset(id: "dataset_id") {
      id
      name
      createdAt
      status
    }
  }
}

Petición

Parámetro Tipo Obligatorio Valor por defecto Descripción
id ID si - ID del dataset
{
  "data": {
    "project": {
      "dataset": {
        "id": "dataset_id",
        "name": "Dataset Name",
        "createdAt": "2020-01-11T11:00:00.000Z",
        "status": "Completed"
      }
    }
  }
}

Respuesta

La respuesta será la misma pero acotada al dataset con el ID especificado en la petición.

Dataset attributes

Es posible consultar todos los atributos de un dataset, o bien filtrarlos a partir de un tipo específico

{
  project(id: "project_id") {
    allDatasets {
      attributes {
        key
        value
        type
      }
    }
    dataset(id: "dataset_id") {
      attributes(type: DOCUMENT_COLUMN) {
        key
        value
        type
      }
    }
  }
}

Petición

Parámetro Tipo Obligatorio Valor por defecto Descripción
type DatasetAttributeType no - Tipos de atributo: DATASET_ATTRIBUTE, DOCUMENT_COLUMN, BENCHMARK_COLUMN
{
  "data": {
    "project": {
      "allDatasets": [
        {
          "attributes": [
            {
              "key": "attribute_key_1",
              "value": "attribute_value_1",
              "type": DATASET_ATTRIBUTE,
            }, {
              "key": "attribute_key_2",
              "value": "attribute_value_2",
              "type": DOCUMENT_COLUMN,
            }, …
          ],
        }, …
      ],
      "dataset": {
        "attributes": [
          {
            "key": "attribute_key_2",
            "value": "attribute_value_2",
            "type": DOCUMENT_COLUMN,
          }, …
        ]
      }
    }
  }
}

Respuesta

Atributo Tipo Descripción
attributes [DatasetAttribute] Atributos basados en los tipos: DATASET_ATTRIBUTE, DOCUMENT_COLUMN, BENCHMARK_COLUMN

Análisis

El uso principal de la API de CX es el análisis de documentos. Ofrecemos tres métodos para ello.

Single-document mode + save (recomendado)

{
  project(id: "project_id") {
    dataset(id: "dataset_id") {
      analyze(
        content: "Este texto se guardará y se podrá consultar en mi dashboard",
        metadata: [{
          columnKey: "dataset_custom_column",
          value: "Este valor se guardará y se podrá consultar en mi dashboard"
        }, … ]
      ) {
        sentiment
        categories
        themes {
          id
          name
          matchingCategories {
            categories {
              id
              name
            }
            count
            percent
          }
        }
      }
    }
  }
}

Es una variante del método anterior. Podemos hacer la misma petición pero especificando también un dataset, en cuyo caso el documento se guardará en la base de datos. Si incluímos el parámetro metadata, estos valores también se guardarán como datos de dicho documento, coincidiendo cada columnKey con un atributo del dataset del tipo DOCUMENT_COLUMN (es posible consultar los atributos de un dataset mediante su respectivo endpoint).

Petición

Parámetro Tipo Obligatorio Descripción
content String Texto a analizar
metadata MetadataInput no Datos personalizados a través de attributes del dataset

Respuesta

{
  "data": {
    "project": {
      "analyze": {
        "sentiment": "POSITIVE",
        "categories": [ "Página web", "Amigable", … ],
        "themes": [
          {
            "id": "theme_id",
            "name": "Theme name",
            "matchingCategories": {
              "categories": [
                {
                  "id": "category_id",
                  "name": "Category name"
                }
              ],
              "count": 2,
              "percent": 33.33,
            }
          }, …
        ],
      }
    }
  }
}
Atributo Tipo Descripción
sentiment Sentiment Sentimiento del texto: POSITIVE, NEGATIVE, OBJECTIVE, UNKNOWN
categories [String] Listado de categorías
themes [Theme] Listado de temas configurados en el proyecto de los cuales han coincidido sus categorías

Single-document mode

{
  project(id: "project_id") {
    analyze(content: "¡Me gusta mucho la web!") {
      sentiment
      categories
      themes {
        id
        name
        matchingCategories {
          categories {
            id
            name
          }
          count
          percent
        }
      }
    }
  }
}

Podemos analizar un único documento si especificamos el texto y un proyecto

Petición

Parámetro Tipo Obligatorio Descripción
content String Texto a analizar

Respuesta

La respuesta será exactamente la misma a la anterior pero bajo el nivel del project especificado en la petición.

Whole-file mode

La idea de este modo es subir un fichero (dataset) para analizar, esperar a que el análisis en bulk termine y descargar el fichero analizado. Los pasos serían:

  1. Crear un dataset (opcional, sólo si no está creado previamente)
{
  createDataset(projectId: "project_id", name: "Project 2", contentColumnKey: "texto") {
    id
  }
}

Petición

Parámetro Tipo Obligatorio Descripción
projectId ID Id del proyecto al que añadir el dataset
name String Nombre del dataset
contentColumnKey String Nombre de la key o columna del .csv que contiene el texto a analizar
{
  createDataset {
    id: "dataset_id"
  }
}

Respuesta

Atributo Tipo Descripción
id ID Id del dataset creado

{
  datasetUploadUrl(id: "dataset_id")
}
  1. Obtener la url de subida del dataset

  1. Subir el fichero a la URL obtenida en el paso anterior. La URL está pre-firmada y tiene un tiempo de expiración de 1 hora. Para subir el fichero, sigue las indicaciones de la documentación de AWS. En particular no olvides especificar la cabeceras Content-Type: text/csv y Content-Length

  1. Esperar a que el análisis termine. Para ello el cliente hará una espera activa, es decir, hará peticiones al estado del dataset hasta que éste pase a Completed

{
  datasetDownloadUrl(id: "dataset_id")
}
  1. Descarga del archivo analizado. Una vez el análisis se haya completado, el fichero estará disponible para la descarga. La URL de descarga contendrá el archivo JSON con todos los documentos analizados. Por seguridad, la URL caducará después de una hora de su generación.

Single-document mode + Filter Routing & Save

# request
{
  client {
    analyze(
      content: "¡Me gusta la web!",
      filters: {
        attributes: [
          { key: "Fuente", value: "Benchmark", type: DATASET_ATTRIBUTE },
          { key: "Estudio", value: "Clientes", type: DATASET_ATTRIBUTE },
          { key: "Subestudio", value: "Website", type: DATASET_ATTRIBUTE },
        ]
      },
      metadata: [{
        columnKey: "dataset_custom_column",
        value: "Este valor se guardará y se podrá consultar en mi dashboard"
      }, … ]
    ) {
      projectId
      datasetAnalysisResults {
        datasetId
        analysisResult {
          sentiment
          categories
          tags
          themes {
            name
            matchingCategories {
              categories {
                id
                name
              }
              count
              percent
            }
            groupingTags {
              id
              name
              orderLevel
            }
          }
        }
      }
    }
  }
}

Permite analizar y guardar en múltiples datasets en una única operación.

Podemos solicitar un análisis especificando además del texto, un filtro de datasets para que tras el análisis se almacene el resultado en todos los datasets que contengan los DATASET_ATTRIBUTE especificados.

El texto se analizará múltiples veces, una para cada dataset, usando las reglas correspondientes al proyecto al que pertenezca el dataset.

Petición

Parámetro Tipo Obligatorio Descripción
content String Texto a analizar
filters AtributesInput no Filtro de datasets que tengan todos los DATASET_ATTRIBUTE especificados
metadata MetadataInput no Datos personalizados a través de attributes del dataset





Respuesta

# response
{
  "data": {
    "client": {
      "analyze": [
        {
          "projectId": "project_id",
          "datasetAnalysisResults": [
            {
              "datasetId": "datset_id",
              "analysisResult": {
                "sentiment": "POSITIVE",
                "categories": [],
                "tags": [
                  "web"
                ],
                "themes": [
                  {
                    "name": "theme_name",
                    "matchingCategories": {
                      "categories": [
                        {
                          "id": "category_id",
                          "name": "Category name"
                        }
                      ],
                      "count": 1,
                      "percent": 25,
                    },
                    "groupingTags": [
                      {
                        "id": "theme_tag_id",
                        "name": "theme_tag_name",
                        "orderLevel": 1,
                      }
                    ]
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  }
}

La respuesta incluirá solo los resultados correspondientes a los datasets para los que fue procesado.

Atributo Tipo Descripción
sentiment Sentiment Sentimiento del texto: POSITIVE, NEGATIVE, OBJECTIVE, UNKNOWN
categories [String] Listado de categorías
themes [Theme] Listado de temas configurados en el proyecto de los cuales han coincidido sus categorías durante el análisis

Referencia

HTTP HEADERS

{
  "Authorization": "Bearer YOUR_TOKEN"
}

La especificación completa del esquema GraphQL puede consultarse en este playground: https://api.cx.sentisis.io/graphql