Interacting with the API using R

Here we'll demonstrate how to interact with the Benchling API using R. To start, let's import some packages:

  • httr: to send and receive request to the Benchling API
  • jsonlite: to help with formatting JSON responses from the API
  • base64enc: to format the API key correctly

If you're missing these packages you can add them with install.packages(c("httr", "jsonlite", "base64enc")).

Getting Set Up

In this example, we'll test interacting with the /custom-entities API endpoints to perform retrieve, create, update and archive operations. The same principle would work with other API endpoints - just check the details of the request and response formats via the API docs.

We'll use our personal API key and store this as an environment variable (BENCHLING_API_KEY). For production use cases, we would recommend using a Benchling App: for more on the various authentication options, see the Authentication guide. We'll create a variable to hold our formatted API key (auth_key below) and define some HTTP headers that will form part of the API request:

library(httr)
library(jsonlite)
library(base64enc)

api_key <- Sys.getenv("BENCHLING_API_KEY")
url = "https://TENANT_NAME.benchling.com/api/v2/custom-entities"
auth_key = paste("Basic", base64encode(charToRaw(paste0(api_key, ":"))))
headers = add_headers("Authorization" = auth_key,
                      "Content-Type" = "application/json",
                      "Accept" = "application/json")

Retrieving an Entity

To check if everything works, we'll make a GET request to the API to retrieve a list of custom entities. We'll specify a schemaId to limit the response to only entities in that schema. To do this, we'll use httr::GET() with the URL and headers we defined from the last step:

# Fetch entities from a schema

response <- GET(url, headers, query = list(schemaId = "ts_XXXXXX"))
content_txt <- content(response, as = "text", encoding = "UTF8")
flattened <- fromJSON(content_txt, flatten = TRUE)
entities <- flattened$customEntities
📘

Making nested JSON more table-like

If you inspect the response you received, you'll notice that the JSON structure is nested. To simplify interacting with the data later on (e.g. via a dataframe) we'll flatten this nested structure and extract the list of entities to a new variable (entities).

Creating an Entity

Now we've successfully retrieved some existing custom entities, we'll try and create a new one using the POST method. To do this will require defining a JSON body to define the fields and metadata for the new entity you wish to create. Give your new entity a name, define the schema it should be registered in with schemaId and the registry the schema belongs to (registryId). Using the namingStrategy of NEW_IDS will automatically generate a new registry ID and use the name we've supplied.

To create the necessary structure for schema fields, create a list of field names. To assign a value to the field, nest a second list with the value to use for each field. That way, when this is encoded as JSON by httr we'll get the correct shape for the API body.

# Create a new entity
body <- list(
  name = "R Thing",
  schemaId = "ts_XXXXXX",
  registryId ="src_XXXXXX",
  namingStrategy = "NEW_IDS",
  fields = list(
    "Thing Property" = list(value = "proper property")
    )
  )

response <- POST(url, headers, body = body, encode = "json")
content_txt <- content(response, as = "text", encoding = "UTF8")
flattened <- fromJSON(content_txt, flatten = TRUE)

Inspect the response to check this worked. If it did, you should see the details of the newly registered entity.

Updating an Entity

So now you've created an entity, how would you go about updating it? To do this we'll use the API ID (this is the id in the response) and the PATCH method.

Let's try to rename the entity we created in the last section. Note that the URL you'll need to use will look like https://TENANT_NAME.benchling.com/api/v2/custom-entities/ENTITY_API_ID. Test this by re-naming the entity from the previous step.

# Update an existing entity
patch_url = paste(url, flattened$id, sep = "/")
body <- list(
  name = "Renamed R Thing"
)

response <- PATCH(patch_url, headers, body = body, encode = "json")
content_txt <- content(response, as = "text", encoding = "UTF8")
flattened <- fromJSON(content_txt, flatten = TRUE)

Check the response to see if the name has been updated. As we decided not to include any fields in the request body, these will remain unchanged.

Archiving an Entity

Finally, to wrap things up, archive the entity you just created. Constructing the body follows a similar process as the last two sections, but specify a list of customEntityIds and a reason for archiving. You can find available archiving reasons via the custom-entities endpoint in the API docs:

Using Made in error as our archive reason looks like this:

# Archive an entity
archive_url <- paste(url,"archive", sep=":")
body = list(
  customEntityIds = list(flattened$id),
  reason = "Made in error"
  )
response <- POST(archive_url, headers, body = body, encode = "json")
content_txt <- content(response, as = "text", encoding = "UTF8")
flattened <- fromJSON(content_txt, flatten = TRUE)