API

Blue has an API (Application Programming Interface), so you can build your own integrations if required.

Blue has 100% API coverage. This means that anything that you can do in any of our apps, you can do programmatically. We have a powerful GraphQL API that has a full playground where you can test your queries and is fully documented.

You can try the playground here:

We have also made a video tutorial that explains how you can leverage the Blue API.

Generate a Token

To start using our API, click on your profile on the top right, and under the profile menu, you'll find the API tab.

In the API tab, click on the button "Generate a Token":

Provide a name for the token and set an expiration date if desired. If you set an expiration date, the API token will automatically stop working after that date.

After generation, you'll receive a Token ID and a Secret ID. The Token ID is your unique identifier for API access, while the Secret ID acts as a password, ensuring secure communication with Blue's API. Remember, the Secret ID is shown only once for security reasons, so store it safely to maintain access to your data through the API.

Security Warning

Ensure you keep your Token ID and Secret ID secure, as anyone with access to these credentials can access your data in Blue.

You have now successfully generated an API token developers can use for custom integrations into Blue.

API Playground

Blue offers an API Playground to experiment with and test your API queries.

  1. Interactive Environment: The Blue API Playground provides a user-friendly interface where you can easily compose and execute GraphQL queries and mutations. It's designed to help developers interact with the GraphQL API without the need for additional tools or writing frontend code.

  2. Real-time Testing and Debugging: One of the key features of the Blue API Playground is the ability to test queries and mutations in real-time. You can write a query or mutation, execute it, and immediately see the response from the server. This immediate feedback is invaluable for debugging and optimizing your queries.

  3. Introspection: Blue's APIs are self-documenting. The Playground leverages this by providing an introspection system. This system allows you to explore the types of data available in the API, including queries, mutations, and the structure of data objects. It's a great way to understand the capabilities of the API and the relationships between different data types.

  4. Documentation Explorer: Blue's API Playground includes a built-in documentation explorer. This section provides detailed information about the schema, including descriptions of types, queries, mutations, and other relevant details. It's a handy reference guide for developers at all levels.

  5. Headers and Variables Support: The Playground allows you to manage HTTP headers and variables easily. This is particularly useful for handling authentication tokens and other configuration details required to interact with the Blue API.

  6. Multi-Tab Interface: Thanks to a tabbed interface, you can simultaneously work with multiple queries or mutations. This makes it easier to manage different aspects of your API interactions simultaneously.

  7. Query History: Blue's API Playground keeps a history of your queries so that you can revisit and re-run past queries. This feature can be a significant time-saver during development and testing.

After generating your token, use the ▶️ button to enter the playground:

Next, you will have to enter your Secret Key, alongside the CompanyID and ProjectID:

To find your CompanyID and ProjectID, you can check the URL of any project you can access. Both IDs are within the URL, as shown below:

https://app.blue.cc/company/{CompanyID}/projects/{ProjectID}/todo

API Documentation

Blue's APIs are self-documenting based on your custom data structure.

The API documentation and schema are seamlessly integrated within the playground, conveniently on the right side. This feature enables users to access comprehensive information about the API's capabilities, including available queries and mutations. A search function is provided for enhanced usability, allowing for quick and efficient query lookup. Users can also download the schema in JSON or SDL formats, facilitating offline reference and further analysis. This integration of documentation within the playground aims to provide developers a comprehensive and user-friendly experience.

API Query Examples

Create a new record
mutation CreateRecord {
  createTodo(
    input: {
      todoListId:"TODOLISTID",
      title: "Test",
      position: 65535
    }
  ) {
    id
    title
    position
  }
}
Toggle Record Status
# Toggle Record Done Status
mutation ToggleRecordDoneStatus {
  updateTodoDoneStatus(todoId: "ENTER RECORD ID") {
    id
    uid
    position
    title
    text
    html
    startedAt
    duedAt
    timezone
    color
    cover
    done
  }
}
Move record to another list
# Move Record To Another List
mutation MoveRecordToAnotherList {
  editTodo(input: { todoId: "ENTER RECORD ID", todoListId: "ENTER LIST ID" }) {
    id
    uid
    position
    title
    text
    html
    startedAt
    duedAt
    timezone
    color
    cover
    done
    todoList {
      id
    }
  }
}
Update record due date
# Update Record Due Date
mutation UpdateRecordDueDate {
  updateTodoDueDate(
    todoId: "ENTER RECORD ID"
    duedAt: "2024-03-08T16:59:59.999Z"
    startedAt: "2024-03-04T17:00:00.000Z"
  ) {
    id
    uid
    position
    title
    text
    html
    startedAt
    duedAt
    timezone
    color
    cover
    done
    todoList {
      id
    }
  }
}
Get list of projects in organisation
# Get List of Projects
query ProjectListQuery {
  projectList(filter: { companyIds: ["ENTER COMPANY ID"] }) {
    items {
      id
      uid
      slug
      name
      description
      archived
      color
      icon
      createdAt
      updatedAt
      allowNotification
      position
      unseenActivityCount
      todoListsMaxPosition
      lastAccessedAt
      isTemplate
      automationsCount
      totalFileCount
      totalFileSize
      todoAlias
    }
    pageInfo {
      totalPages
      totalItems
      page
      perPage
      hasNextPage
      hasPreviousPage
    }
  }
}
Delete Record
# Delete a Record
mutation DeleteARecord {
  deleteTodo(input: { todoId: "ENTER RECORD ID" }) {
    success
  }
}
Get List of Records Between a Start and Due Date
# Get List of Records Between a Start and Due Date
query ListOfRecordsBetweenAStartAndDueDate {
  todoQueries {
    todos(
      filter: {
        companyIds: ["ENTER COMPANY ID"],
        startedAt: "2024-04-07T17:00:00.000Z"
        dueEnd: "2024-04-10T16:59:59.999Z"
      }
      skip: 20
      limit: 20
      sort: [position_ASC]
    ) {
      items {
        id
        uid
        position
        title
        text
        html
        startedAt
        duedAt
        timezone
        color
        cover
        done
      }
      pageInfo {
        totalPages
        totalItems
        page
        perPage
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
Get list of users in organisation
 Get list of users in organisation
query GetListOfUsersInOrganisation {
  companyUserList(companyId: "ENTER COMPANY ID") {
    users {
      id
      uid
      username
      email
      dateOfBirth
      phoneNumber
      firstName
      lastName
      fullName
      isEmailVerified
      jobTitle
      locale
      lastActiveAt
      createdAt
      updatedAt
      isOnline
      timezone
      theme
    }
    pageInfo {
      totalPages
      totalItems
      page
      perPage
      hasNextPage
      hasPreviousPage
    }
  }
}
Get list of tags within a project
# Get List of Tags within Projects
query ListOfTagsWithinProjects {
  tagList(filter: { projectIds: ["ENTER PROJECT ID"], excludeArchivedProjects: false }) {
    items {
      id
      uid
      title
      color
      project {
        id
        name
      }
      createdAt
      updatedAt
    }
    pageInfo {
      totalPages
      totalItems
      page
      perPage
      hasNextPage
      hasPreviousPage
    }
  }
}
Get list of records within a project
# Get List of Records within Project
query ListOfRecordsWithinProject {
  todoQueries {
    todos(
      filter: { companyIds: ["ENTER COMPANY ID"], projectIds: ["ENTER PROJECT ID"] }
      skip: 20
      limit: 20
      sort: [position_ASC]
    ) {
      items {
        id
        uid
        position
        title
        text
        html
        startedAt
        duedAt
        timezone
        color
        cover
        done
      }
      pageInfo {
        totalPages
        totalItems
        page
        perPage
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
Tag an existing record
# Update Existing Record (Add Tag)
mutation UpdateExistingRecordAddTag {
  setTodoTags(
    input: {
      todoId: "RECORDID"
      tagIds: ["TAGID1", "TAGID2"]
    }
  )
}
Get all records assigned to a specific user across all projects
 # Get all records assigned to a specific user across all projects
query GetAllRecordsAssignedToASpecificUserAcrossAllProjects {
  todoQueries {
    todos(
      filter: {
        companyIds: ["ENTER COMPANY ID"]
        assigneeIds: ["ENTER ASSIGNEE ID"]
      }
      skip: 20
      limit: 20
      sort: [position_ASC]
    ) {
      items {
        id
        uid
        position
        title
        text
        html
        startedAt
        duedAt
        timezone
        color
        cover
        done
      }
      pageInfo {
        totalPages
        totalItems
        page
        perPage
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
Update single line text custom field in existing record
# Update Existing Record (Single Line Text Custom Field)
mutation UpdateExistingRecordSingleLineTextCustomField {
  setTodoCustomField(
    input: {
      todoId: "clmu9ec9301k4n01gz8v2n10u"
      customFieldId: "cltzkh0wi02mv10w3f6t3sv6k"
      text: "Test"
    }
  )
}

Need more help?

Feel free to reach out to our team at help@blue.cc for assistance. We also offer professional services for custom integrations.

Example API Usage in Python

To get started with the Blue API, you need to set up the API endpoint in your code. The Blue API uses a GraphQL endpoint for making requests, which is typically https://api.blue.cc/graphql. This endpoint URL should be used when making API requests to interact with the Blue API.

Authentication is required to access the Blue API. You'll need to obtain the necessary API keys, which include the X-Bloo-Token-ID (your Blue token ID), X-Bloo-Token-Secret (your Blue token secret), X-Bloo-Company-ID (the ID or slug of your company), and X-Bloo-Project-ID (the ID or slug of your project). These keys should be included in the headers of your API requests to authenticate and authorize your access to the Blue API.

The Blue API uses GraphQL, a query language that allows you to define specific queries and mutations to interact with the data. Queries are used to retrieve data from the API, while mutations are used to modify data. You need to define the necessary queries and mutations based on your requirements. For example, to retrieve a list of todos, you can use a query like:

query ListOfRecordsWithinProject {
  todoQueries {
    todos(
      filter: { companyIds: ["your-company-id"], projectIds: ["your-project-id"] }
      limit: 100
      sort: [position_ASC]
    ) {
      items {
        id
        title
      }
    }
  }
}

To interact with the Blue API, you need to make HTTP requests to the GraphQL endpoint. Typically, you'll use the POST method to send GraphQL queries and mutations. Include the necessary headers, including the authentication keys, in your requests. The request payload should include the GraphQL query or mutation and any required variables. Here's an example of making a request using Python's requests library:

import requests

endpoint = "https://api.blue.cc/graphql"
headers = {
  "X-Bloo-Token-ID": "your-token-id",
  "X-Bloo-Token-Secret": "your-token-secret",
  "X-Bloo-Company-ID": "your-company-id",
  "X-Bloo-Project-ID": "your-project-id"
}
payload = {
  "query": "your-graphql-query",
  "variables": {"variable1": "value1", "variable2": "value2"}
}

response = requests.post(endpoint, json=payload, headers=headers)

After making a request to the Blue API, you'll receive a response containing JSON data with the requested information or the result of the mutation. Parse the JSON response to extract the relevant data and handle any errors or exceptions that may occur during the API request.

The Blue API supports pagination and filtering options for queries. You can use the limit and skip parameters to control the number of results returned and the starting point of the result set. Additionally, you can use the filter parameter to specify criteria for filtering the results based on attributes like companyIds and projectIds.

Below is the code for a sample Python app that gets the complete list of records from a project, asks you to pick one, then gives you the list of tags and asks you to choose a tag. The record is then updated in Blue with the selected tag.

import requests

# Define your GraphQL endpoint
endpoint = "https://api.blue.cc/graphql"

# Define your GraphQL queries and mutation
query_todos = """
query ListOfRecordsWithinProject {
  todoQueries {
    todos(
      filter: { companyIds: ["COMPANYID"], projectIds: ["PROJECTID"] }
      limit: 100
      sort: [position_ASC]
    ) {
      items {
        id
        title
      }
    }
  }
}
"""

query_tags = """
query ListOfTagsWithinProjects {
  tagList(filter: { projectIds: ["PROJECTID"], excludeArchivedProjects: false }) {
    items {
      id
      title
    }
  }
}
"""

mutation_update_todo = """
mutation UpdateExistingRecordAddTag($todoId: String!, $tagIds: [String!]!) {
  setTodoTags(
    input: {
      todoId: $todoId
      tagIds: $tagIds
    }
  )
}
"""

# Define the request payload
payload_todos = {
    "query": query_todos
}

payload_tags = {
    "query": query_tags
}

# Define the authentication headers
headers = {
    "X-Bloo-Token-ID": "TOKENID",
    "X-Bloo-Token-Secret": "TOKEN-SECRET",
    "X-Bloo-Company-ID": "COMPANY-ID",
    "X-Bloo-Project-ID": "PROJECT-ID"
}

# Make the POST request to the GraphQL endpoint with authentication headers
response_todos = requests.post(endpoint, json=payload_todos, headers=headers)
response_tags = requests.post(endpoint, json=payload_tags, headers=headers)

# Check the response status code
if response_todos.status_code == 200 and response_tags.status_code == 200:
    # Request was successful
    data_todos = response_todos.json()
    data_tags = response_tags.json()

    # Extract the 'items' list from the response data
    items_todos = data_todos['data']['todoQueries']['todos']['items']
    items_tags = data_tags['data']['tagList']['items']

    # Print the list of todos
    print("List of Todos:")
    for index, item in enumerate(items_todos, start=1):
        print(f"{index}. {item['title']}")

    # Ask the user to choose a todo
    todo_choice = int(input("Enter the number of the todo you want to categorize: "))
    selected_todo = items_todos[todo_choice - 1]

    # Print the list of tags
    print("\nList of Tags:")
    for index, item in enumerate(items_tags, start=1):
        print(f"{index}. {item['title']}")

    # Ask the user to choose tags
    tag_choices = input("Enter the numbers of the tags you want to assign (comma-separated): ")
    selected_tag_ids = [items_tags[int(choice) - 1]['id'] for choice in tag_choices.split(",")]

    # Print the selected todo and tags
    print("\nSelected Todo:")
    print(selected_todo['title'])
    print("\nSelected Tags:")
    for tag_id in selected_tag_ids:
        tag = next(item for item in items_tags if item['id'] == tag_id)
        print(tag['title'])

    # Update the selected todo with the selected tags
    mutation_variables = {
        "todoId": str(selected_todo['id']),
        "tagIds": [str(tag_id) for tag_id in selected_tag_ids]
    }
    payload_update_todo = {
        "query": mutation_update_todo,
        "variables": mutation_variables
    }
    response_update_todo = requests.post(endpoint, json=payload_update_todo, headers=headers)

    if response_update_todo.status_code == 200:
        print("\nTodo updated successfully with the selected tags.")
    else:
        print("\nFailed to update the todo with the selected tags.")
        print("Response:", response_update_todo.json())

else:
    # Request failed
    print("Request failed with status code:", response_todos.status_code, response_tags.status_code)

Last updated