Overview

Slide Score API allows programmatically uploading slides, creating studies and downloading results.

You can for example:

An API token is used to secure access to the API, the token can only be created by site administrators.

This API is based on common tasks that need to be done.

You can either write a script that sends the HTTP requests directly or make use of C# or Python SDKs. If you use C# have a look at an example client in C# that includes SlideScoreClient.cs class that will help you make the API calls.

For Python install the SDK module with pip install slidescore-sdk. The APIClient class in the SDK has methods that directly correspond to the API calls. See the Python SDK source repo for examples and more details. Alternatively, Netherlands Cancer Institute maintains a fork with support for shapely and GeoJSON

Note that this documentation assumes some programming knowledge and is a work in progress.

Authentication

Before you can access the API you need an access token.

Login as Site Administrator and go to the Create Token page or click the Create API token button in study administration.

Fill in the name and expiration date of the token. Check below what methods you need to call and give the token only the rights that are needed only for the necessary studies.

This API token needs to be supplied for all API calls in the Authorization HTTP Header like this:

Authorization: Bearer hblJlYWRPbmx5U....3R1ZGllcyI6IiIsIkNhbk1

When you no longer need it you can give it up by calling POST /Admin/GiveupToken with the token as POST parameter.

These are the capabilities that the token can have:

Can upload

API token can upload slides and configuration files

Can create upload folders

API token can create folders on the server to create new studies

Can upload scores

API token can upload results and annotations to studies. This is useful for image analysis workflows - models can push their results to Slide Score.

Can download configuration files for studies

API token can request the current configuration of studies in the form of configuration files. This is useful if you want to synchronize external database with Slide Score configuration.

Can read raw tiles from slides and their metadata

API token can read image tiles. The API has 3 ways to access the pixels GetScreenshot (the most high level call - request a region and level of detail), GetTile (DeepZoom-like request), GetRawTile (request that's forwarded to the slide libraries - OpenSlide and others. You need to check the image metadata first - levels in the slide and so on).

With this right image analysis algorithm can request (and cache) the pixels of slides.

Can upload only in folders

This is a restriction.

Semicolon-separated list of folders on the server to which the token can upload. If you leave it empty API token can upload slides in any folder. If you set it API token won't be allowed to upload to any other folders.

Can read (get scores, images) only these studies

This is a restriction.

Semicolon-separated list of studies which the token can read - download scores (with Can get scores of any study), images, ... If you leave it empty API token can read any study. If you set it API token won't be allowed to read any other studies.

Can modify (upload images, delete, reimport) only these studies

This is a restriction.

Semicolon-separated list of studies which the token can modify - add slides, reimport, ... If you leave it empty API token can modify any study. If you set it API token won't be allowed to modify any other studies.

Can create studies

Unused at the moment

Can reimport studies

API token can (after uploading configuration files and slides) re-import a study.

This will read configuration files and apply changes to the study. Note that it can overwrite changes made manually in the administration interface - you can use GetConfigFiles to create up-to-date config files and change only those.

You always need to run reimport after you upload the slide(s) using the API otherwise they won't show up.

Can delete owned studies

Unused at the moment

Can get scores of owned studies

API token can retrieve (unless Can read blocks it) scores of studies that the token has created.

Can get scores of any study

API token can retrieve (unless Can read blocks it) scores of any study.

Can get study configuration

API token can retrieve (unless Can read blocks it) configuration files of any study and can send emails on behalf of the Slide Score server.

Can download

API token can download actual files containing the image data in original format (unless Can read blocks it)

Can delete

API token can delete slides from a study (unless Can modify blocks it)

Can handle paths

API token can request and update file paths of the slide files. This can be used for e.g. archival of unused slides.

Get study status

Get results

GET Api/Scores

Required rights: Can read the study, Can get scores of owned studies or at least Can get scores of any study if it was created by the API token

Parameters:

Name Type Required Explanation
studyId int yes Study which you want to download scores from
question string no Optional, return only answers to this question
email string no Optional, return only answers by this user
imageid string no Optional, return only answers for this image
caseid string no Optional, return only answers for this case

Returns tab separated file with all the scores from the study. The format is the same as when downloading results manually.

GET Api/GetStudiesUpdated

Required rights: Can read, Can get scores of owned studies or at least Can get scores of any study if it was created by the API token

Parameters:

Name Type Required Explanation
since string yes ISO 8601 date and time string with timezone

Returns JSON object with an array of integer IDs in StudyIDs - IDs of studies that had results submitted since the given date You can use this method if you are periodically checking for new results.

Get study structure

GET Api/Studies

Required rights: Can read

Parameters: None

Returns

JSON array of all studies this token can view with their ID, Name, FriendlyName (label or alias), Folder and PublishedOn (studies that have not been published yet are invisible for users without access to study administration).

GET Api/Images

Required rights: Can read

Parameters:

Name Type Required Explanation
studyId int yes Study which you want to list images from

Returns

JSON array of images with their ID and Name. Useful for creating reports with links to view the slide. You can construct an URL like https://server/Image/Details?imageId=1&studyId=2 that will open image with ID=1 in study with ID=2. For TMAs you can use additional GET parameters to select single or few cores:

GET Api/Cases

Required rights: Can read

Parameters:

Name Type Required Explanation
studyId int yes Study which you want to list cases from

Returns

JSON array of cases with their ID and Name.

GET Api/Questions

Required rights: Can read

Parameters:

Name Type Required Explanation
studyId int yes Study which you want to list questions from

Returns

JSON array of questions with their ID, Name, Type, TypeName and ValuesAllowed.

GET Api/GetSlidePath

Required rights: CanHandlePaths

Parameters:

Name Type Required Explanation
imageId int yes Slide ID for which to retrieve the file path

Returns JSON object with fields success (must be true) and path - path relative to the application folder or error field.

GET Api/GetSlideDescription

Required rights: None (must be able to read the study)

Parameters:

Name Type Required Explanation
imageId int yes Slide ID for which to retrieve the description

Returns JSON object with fields success (must be true) and description (HTML-encoded) or error field.

GET Api/GetCaseDescription

Required rights: None (must be able to read the study)

Parameters:

Name Type Required Explanation
caseId int yes Case ID for which to retrieve the description

Returns JSON object with fields success (must be true) and description (HTML-encoded) or error field.

POST Api/Publish

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
studyId int yes Study that should be published

Publish the study so that users without Edit right can see it.

POST Api/Unpublish

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
studyId int yes Study that should be unpublished

Unpublish the study so that users without Edit right can not see it.

GET Api/DownloadSlide

Required rights: Can read, Can download

Parameters:

Name Type Required Explanation
studyId int yes Study which you want to download image from
imageId int yes Which image to download

Returns

The slide file. Note that it can be very large (>10GB). Please, use the file name from the Content-Disposition header to set the correct file extension on the downloaded file.

Upload

Uploading a file has 3 steps:

  1. POST RequestUpload
  2. Upload using Tus.io
  3. POST FinishUpload

POST RequestUpload

Required rights: Can upload

Parameters:

Name Type Required Explanation
filename string yes Filename (without path) to use for the file on the server - this can be used to rename slides
folder string no Folder on the server (under the images root) to which the file should be uploaded. Note that you can only upload to the root folder, it subfolders and their subfolders, if empty studyId has to be set and it will determine the folder
studyId int no if folder is not set it will be set to name of this study

Returns

JSON object with token attribute. This is the upload token you will need for uploading.

Upload using Tus.io

You can use any of Tus.io's clients to perform the upload. Add uploadtoken that you've received from previous step and API token (as apitoken) as metadata. You will receive fileid that you will need in the next step

POST FinishUpload

Required rights: Can upload

Parameters:

Name Type Required Explanation
token string yes upload token from RequestUpload
id string yes fileid from Tus.io

Returns

JSON string containing "OK"

When Tus is done uploading you have to commit the upload using this method.

POST Api/AddSlide

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
studyId int yes Study where the slide should be added
path string yes The relative server path to a file

This method directly adds a previously uploaded slide to the study.

It's possible to upload scoring results to Slide Score - this is useful if you have some legacy slides that you want to review or you are moving all the data to a single repository - Slide Score. This is also very useful for Active learning - training image analysis models with manual corrections with quick turn-around.

POST Api/UploadResults

Required rights: Upload scores

Parameters:

Name Type Required Explanation
studyId int yes Study where results should be imported
results string yes The results should have the same format as when you download them from Slide Score

This is the format of results expected:

ImageID(tab)Name(tab)By(tab)(optionally: TMA Row(tab)TMA Col(tab)TMA Sample(tab))Question(tab)Answer

Updating slide properties

POST Api/SetSlideResolution

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
studyId int yes Study where the slide should be added
imageId int yes Slide ID that should be changed
micronsPerPixel double yes new value to set, typical value if 0.2 for 40x slides. This means that 1 pixel is 0.2 microns wide and tall, must be > 0 and < 1 000 000

Change the resolution of the slide. This can be useful when the slide file contains no or incorrect resolution information.

POST Api/SetSlideDescription

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
studyId int yes Study where the slide should be added
imageId int yes Slide ID that should be changed
description string yes new slide description. Can contain limited html formatting

Change the description of the slide. Slide Score severely limits HTML tags and attributes that can be used in the description to make hacking more difficult, so it's best to first create a description using the editor for an existing slide and then adapt that.

POST Api/UpdateSlideName

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
imageId int yes Slide ID that should be changed
newName string yes new slide name

Change the name of the slide.

POST Api/UpdateCaseName

Required rights: None (must be able to modify the study)

Parameters:

Name Type Required Explanation
caseId int yes Case ID that should be changed
newName string yes new slide name

Change the name of the case.

POST Api/UpdateSlidePath

Required rights: CanHandlePaths

Parameters:

Name Type Required Explanation
imageId int yes Slide ID that should be changed
newPath string yes new slide file path relative to the application folder

Change the path of the slide files. Note that the file must exist. Returns JSON object with fields success (must be true) or error field.

POST Api/DeleteSlide

Required rights: Can modify, Can delete

Parameters:

Name Type Required Explanation
studyId int yes Study from which you want to delete the image
imageId int yes Which image to delete

Returns

Empty result on success.

Annotation format

Annotations are stored as JSON arrays of objects in Slide Score. All coordinates and sizes are in image pixels (at the highest resolution).

AnnoPoints format

Answers to AnnoPoints type questions are stored as arrays of objects with x and y coordinates, for example:

[{"x": 37591, "y": 18439}, {"x": 37518, "y": 18420}, ... ]

AnnoShapes format

Answers to AnnoShapes type questions are stored as arrays of objects. Each object has a type and other common properties and some type-specific properties:

Common properties

Name Type Required Explanation
type string yes One of: polygon, polyline, ellipse, rect (for rectangle), brush or heatmap
modifiedOn Date no Datetime of last modification (in UTC timezone), for example "2022-07-12T13:55:12.458Z"
area string no Total area of annotation including unit, for example "105 mm2", if not present it will be recalculated next time the annotation is changed by the user
labels array of Labels no Array of Label objects (see below)

Polygon and polyline properties

Name Type Required Explanation
points array of coordinates yes array of coordinate objects specifying the vortices of the polygon. Clockwise or anticlockwise. Last and first point will be connected by line only if type is polygon. For example [{"x": 37591, "y": 18439}, {"x": 37518, "y": 18420}, ... ]

Ellipse properties

Name Type Required Explanation
x,y number yes Coordinates of the center of the ellipse
width, height number yes Total width and height (radius times 2) of the ellipse.

Rectangle properties

Name Type Required Explanation
corner coordinate yes Coordinates of the left top corner of the rectangle
size coordinate yes Width (x) and height (y) of the rectangle.

Brush properties

Name Type Required Explanation
positivePolygons array of array of coordinates yes Set of polygons that make the outline of the shape
negativePolygons array of array of coordinates yes Set of polygons that make the "holes" of the shape, note that holes can't contain any outline polygons

Heatmap properties

Name Type Required Explanation
data array of array of numbers yes Data specifying the heatmap. Rectangular (all arrays have the same length) array of arrays of value 0 to 255. 0 is always transparent,
x,y coordinates no Coordinates of the upper left corner where to place the heatmap, if not specified it is placed at 0,0
width, height number no Width and height of the area where to place the heatmap. Cannot be combined with downscale. If neither are specified heatmap is stretched to the rest of the image ie. from (x,y) to (maxx, maxy)
downscale number no How width (in image pixels) is one data point of the heatmap. Cannot be combined with width or height. If neither are specified heatmap is stretched to the rest of the image ie. from (x,y) to (maxx, maxy)

Label properties

Name Type Required Explanation
label string yes Text of the label
x,y number yes Coordinates where should the label be displayed
whenToShow string yes Whether the label should be shown always or only when user moves their mouse over the shape to which the label belongs, values allowed: "always" or "mouseover"
fontSize number yes Size of the text in image pixel coordinates

ASAP interoperability

Slide Score supports exchanging annotations with ASAP. Since both programs use slightly different way to organize the annotations you might want to specify how to map colors in ASAP to questions in Slide Score.

GET Api/ExportASAPAnnotations

Required rights: Can get scores

Parameters:

Name Type Required Explanation
imageId int yes Image for which annotations should be exported
user string yes User whose annotations/answers should be exported
question string no Which question to export if there are multiple annotation-type questions. Can be empty to export all

Returns

Single XML file containing annotations for image imageId created by user user for the question (it has to be of type AnnoShapes or AnnoPoints). This XML file can be loaded straight to ASAP.

POST Api/UploadASAPAnnotations

Required rights: Upload scores

Parameters:

Name Type Required Explanation
imageid int yes Image for which annotations should be imported
user string yes User under whose account these annotations/answers should be imported
asapAnnotation string yes Contents of the ASAP XML file
questionsMap string no Defines mapping between colors used in the annotation file and questions defined in the study in Slide Score, see below

questionsMap: Each mapping is on a new line and consists of color hex code, semicolon (;) and the name of the question. Example mapping file:

#f0f0f0;Lymphocytes
#ff0000;Tumor area

If you don't specify questionsMap each new color of annotations will be imported into a new question called "Imported annotation #".

Returns

JSON object with attribute Success (true for successful import) and Log containing log of the the import detailing generated questions and more.

Screenshots

GET Api/GetScreenshot

Required rights: Can get scores, Can get pixels

Parameters:

string withAnnotationForUser, int x, int y, int width, int height, int level, string scoreIDs

Name Type Required Explanation
imageID int yes Image to screenshot
x int no screenshot top-left corner coordinate in pixels in most detailed level, if x, y, width and height are 0 the whole image is imaged
y int no screenshot top-left corner coordinate in pixels in most detailed level, if x, y, width and height are 0 the whole image is imaged
width int no screenshot width in pixels in most detailed level, if x, y, width and height are 0 the whole image is imaged
height int no screenshot height in pixels in most detailed level, if x, y, width and height are 0 the whole image is imaged
withAnnotationForUser string no If the study has annotation-type questions you can include particular user's answers-annotations in the screenshot
scoreIDs string no If the study has annotation-type questions you can include only particular question IDs (comma-separated) to only select some annotations to include. If you leave it empty all annotations by withAnnotationForUser will be added. Cannot be specified in combination with question
question string no If the study has annotation-type questions you can include one particular annotation-type question to include. If you leave it empty all annotations by withAnnotationForUser will be added. Cannot be specified in combination with scoreIDs
level int yes DeepZoom level - binary exponent of the larger dimension of the resulting image - 11 for an image with larger dimensions between 1024 and 2048 pixels, 12 for 2048 - 4096 and so on

Returns

JPEG file with the screenshot. Note that this method can be slow and won't work for more than ~50 megapixel images. Please, request smaller ones and stitch them together.

Note that x, y, width and height all refer to the level with the highest detail so if you are requesting lower detail levels you need to multiply them by a factor of 2^(difference in levels). For example if the image is 87140x87140 pixels, the highest-detail level is 17. If we request level 12, we are looking 5 times zoomed out image. One pixel in level 12 equals 2^5=32 pixels in level 17. If we need a 100x100 image we need to request width and height equal to 32*100=3200.

Error codes: 401 for invalid token, token that doesn't have enough rights, 404 if image doesn't exist, 400 if both scoreIDs and question are specified

Sending emails

POST Api/SendEmail

Required rights: Can get configuration files

Parameters:

Name Type Required Explanation
studyId int yes Study that email is related to
to string yes Semicolon (;) separated list of email addresses to send it to, they have to be configured as users of the study
subject string yes Email Subject line
body string yes Text of the email to send. In plain text. It can contain token <LINK:Start Scoring> which will be replaced with a link to start scoring the study

It will send an email to all addresses listed in to. The From address will be info@slidescore.com.

Returns

Empty JSON object if successful.

Study configuration

Studies are set up by uploading configuration files to the root folder and image files into a subfolder. If the subfolder has the same name as the study all image files there are automatically uploaded. Otherwise, you need to reference them with an study.<studyname>.images file (see Slides for more).

Users

Users are configured in a file study.<studyname>.emails. This file contains one user of the study per line.

By default they get only CanScore right. You can specify viewonly or additional rights (cangetresults, canscore, canedit) separated by comma if you want to change that. Note that you can't remove rights from a user this way, they are only added. To remove user's rights, use the administration interface.

For example:

email@example.com
email2@example.com;viewonly
email3@example.com;canscore,canedit,cangetresults

Slides

By default all slides in a folder that has the same name as the study are imported. Additionally, this folder can contain *.images file that references images, one image per line. Note that you don't have to reference the images that are in the study folder. You can also specify TMA map, rotation to use with the image and potential new name, like this:

../otherfolder/1.svs
../otherfolder/2.svs;study.example.map;90
../otherfolder/011938r082.tif;;Nice Image

Note that TMA map, rotation or new name can be left out or empty and they will be ignored.

TMA Maps

You can import a TMA Map in two ways - either reference it in an .images file in study's folder or create a map file with the name study.<studyname>.map<additional identifier> in the root folder. The map file can be divided into a header and the actual map.

Header contains properties and their values separated by a colon (:). Header properties can be:

The header is terminated by an empty line. The map starts under it. Each line in a map is a row of TMA core IDs, columns are separated by TAB character. If a line doesn't have the same number of columns as the longest row it will be padded by empty cores.

Here is an example of a simple map:

tmas: 1.svs
controls: ctrl
ignore: 0, empty
force: true

1   1   1   ctrl    ctrl    ctrl
2   2   2   3   3   3
0   0   0   4   4   4
5   5   5   empty   empty   empty

The imported map applies to 1.svs and looks like this

Example TMA map

Study Settings

Study settings are configured in the study.<studyname>.config file.

It contains properties of the study, in the format property name: value (or value1,value2)

Recognized properties:

allowchangingscores
allowresultscomparisonforeveryone
allowsharingslidesanonymously
artid
disallownavigation
disallowrewritingscores
disease
folder
friendlyname
hideslidenames
organ
scoretmacoresatonce
showduplicates
showlabels
showotherpeoplesscores
showslidenames
showthumbnails
showtmasampleids
stainings

Questions

The questions that form study's scoring sheet are listed in study.<studyname>.scores. The format is a bit complicated, it's best to create the scoring sheet in the Question editor, click the Share button and copy the value of the f URL parameter to the questions file. In principle it has one line per question - name of the question followed by a semicolon (;), question type (FreeText, DropDown, Percentage, Checkbox, ...), followed by another semicolon and optionally other configuration for the question (options for a DropDown for example).

Importing

After uploading all important files call the POST Api/Reimport method to create the study based on the config files and return a log of how did it go.

POST Api/Reimport

Required rights: Can reimport studies

Parameters:

Name Type Required Explanation
studyName string yes Name of the study to (re-)import
ignoreImageErrors true or false no If true the import process doesn't stop after encountering problems with a slide but try to import all slides

Returns

String with log of the import process

If you need to change an existing study you can upload modified config files and run Reimport again.

Note that nothing gets removed, only added. Furthermore, if you've removed an image or users using the administration interface it will be added again if it is in the config files.

Note that you can't delete files on the server only overwrite them.

Synchronizing

All users with CanEdit right can enter the administration interface and make changes to the study. Often it's needed to rotate some images, adjust a TMA map or reorder questions. However, when you call Reimport next time these changes can be overwritten. To prevent this from happening use GET Api/GetConfig method with study ID as a parameter. It will return the complete configuration of a study as an object graph (for details see the API client).

Clone a study

You can easily clone a study as it is by requesting the configuration files of an existing study using Get Api/GetConfigFiles method with study ID as a parameter. This will return JSON object with content of all the configuration files. Note that they are dynamically generated from the database - these are not necessarily the same files that were used to create the study.

Getting pixel data

Slide Score can act as a platform for storing the slides and serving them for other applications. The API has 2 methods how to request the tiles that make up pathology slides:

  1. Accessing the Deep Zoom tiles using GetImageMetadata, GetTileServer and requests to /i/ endpoint. This is the high-performance method. It serves tiles in different levels, each level being twice as detailed as the previous one. It increases complexity of the client code as each slide can have different number of levels and tile size and they need to be stitched together to create the image.
  2. GetScreenshot for low volume of requests, if you need the slide with annotation or just a low resolution image.

Deep Zoom tiles

Deep Zoom is a technology for displaying high resolution images in the browser. Slide Score uses it to display slides to the users. It is possible for your script to use the same interface. As it's highly optimised for speed, it should be the fastest method of accessing the slides remotely.

When using Deep Zoom a large image is requested in parts - tiles. These tiles need to be stitched together to create the whole image. To support zooming in and out of image Deep Zoom defines levels. The last level has all the detail that is actually in the image. The level above it is is twice smaller (its width and height are both half so you could say it's 4 times smaller). And so on and on until level 0 which is 1x1 pixel. So, if you have an image that's 4096x4096 pixels it would have 12 levels (as 2^12 is 4096), level 12 would be 4096x4096, level 11 would be 2048x2048 and so on.

Now back to the tiles. Remember that we can't request the whole level as it might be too large. The pixels are requested in tiles. For example the image from last paragraph might have tiles with size 256x256 pixels. In that case level 12 would have 4096/256=16 rows and columns of tiles. Level 11 would have 8 and so on.

When using this method you need to first request access to the /i/ endpoint by calling GetTileServer - this will return two tokens for authentication: one needs to be supplied in a cookie and another in the URL. This replaces the standard API authentication for the /i/ endpoint. You will also need to request image dimensions, tile size and levels by calling GetImageMetadata. Then you can start requesting the JPEG encoded tiles using the /i/ endpoint.

GET Api/GetImageMetadata

Required rights: Can get pixels

Parameters:

Name Type Required Explanation
imageId int yes ID of the image to access

Returns

JSON object with success flag and SlideMetadata object:

long Level0TileWidth
long Level0TileHeight
int OSDTileSize
double MppX
double MppY
double ObjectivePower
string BackgroundColor
int LevelCount
long Level0Width
long Level0Height
double[] Downsamples

OSDTileSize holds the size of tiles (256px in the example above)

Level0Width and Level0Height is the width and height of the largest most detailed level (note that in Deep Zoom the most detailed level is the last one not level 0). You will need to calculate the number of levels from the larger of width and height.

GET Api/GetTileServer

Required rights: Can get pixels

Parameters:

Name Type Required Explanation
imageId int yes ID of the image to access

Returns

JSON object with cookiePart, urlPart (to be used in the calls to /i/ endpoint) and expiresOn - a date by which this token needs to be renewed.

GET Api/GetTokenExpiry

Required rights: Can get pixels

Parameters:

Name Type Required Explanation
cookiePart string yes cookie part of the token
urlPart string yes URL part of the token

Returns

JSON object with expiresOn - a date by which this token needs to be renewed.

Calling the /i/ endpoint

You can request the JPEG encoded tiles at URL

/i/<imageID>/<urlPart>/i_files/<level>/<column>_<row>.jpeg

replace urlPart with the respective authentication token from GetTileServer, imageID with the ID of the requested image, level, column and row with the coordinates of the tile. You also need to include a cookie with name "t" and value of the cookiePart token from GetTileServer.

For example

/i/53926/318yu2xYJBUK6IKpsb/i_files/9/0_0.jpeg

To request the tile from upper left corner of image with ID 53926. It's from a level 9 which has size at most 512x512.