HTTP API

The SampleDB HTTP API makes it possible to use HTTP requests to perform most actions that can be done via the web frontend. This can be very useful for automated data entry, e.g. for uploading metadata from instrument control software, and retrieval, e.g. for data analysis.

There are libraries for sending HTTP requests for most programming languages, and users of Python or Matlab can use the sampledbapi package developed at WWU Münster for even simpler use of the HTTP API.

Authentication

The SampleDB HTTP API either uses Basic Authentication using normal user credentials (e.g. using the header Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=) or Bearer Authentication using the API token (e.g. using the header Authorization: Bearer bf4e16afa966f19b92f5e63062bd599e5f931faeeb604bdc3e6189539258b155). API tokens are meant as an alternative method for authentication for individual scripts and allow you to monitor the requests made with the token. You can create an API token when editing your Preferences. If you have a two-factor authentication method enabled, you cannot use your user credentials to use the API and will have to use an API token instead.

You can use these authentication methods to create a short-lived access token, along with a refresh token to generate new access tokens.

Please make sure to use HTTPS when accessing the API.

Objects

Reading a list of all objects

GET /api/v1/objects/

Get a list of all objects visible to the current user.

The list only contains the current version of each object. By passing the parameter q to the query, the Advanced Search can be used. By passing the value false to the parameter use_advanced_search, the Simple Search can be used instead. By passing the parameters action_id or action_type objects can be filtered by the action they were created with or by their type (e.g. sample or measurement).

Instead of returning all objects, the parameters limit and offset can be used to reduce to maximum number of objects returned and to provide an offset in the returned set, so allow simple pagination.

If the parameter name_only is provided, the object data and schema will be reduced to the name property, omitting all other properties and schema information.

If the parameter get_referencing_objects is provided, the object data include referencing object IDs.

Example request:

GET /api/v1/objects/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "object_id": 1,
        "version_id": 0,
        "action_id": 0,
        "schema": {
            "title": "Object Information",
            "type": "object",
            "properties": {
                "name": {
                    "title": "Object Name",
                    "type": "text"
                }
            }
        },
        "data": {
            "name": {
                "_type": "text",
                "text": "Example Object"
            }
        }
    },
    {
        "object_id": 2,
        "version_id": 3,
        "action_id": 0,
        "schema": {
            "title": "Object Information",
            "type": "object",
            "properties": {
                "name": {
                    "title": "Object Name",
                    "type": "text"
                }
            }
        },
        "data": {
            "name": {
                "_type": "text",
                "text": "Other Object"
            }
        }
    }
]
Status Codes:

Getting the current object version

GET /api/v1/objects/(int: object_id)

Redirect to the current version of an object (object_id).

Example request:

GET /api/v1/objects/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 302 Found
Location: /api/v1/objects/1/versions/0
Status Codes:

Reading an object version

GET /api/v1/objects/(int: object_id)/versions/(int: version_id)

Get the specific version (version_id) of an object (object_id).

Example request:

GET /api/v1/objects/1/versions/0 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "object_id": 1,
    "version_id": 0,
    "action_id": 0,
    "user_id": 1,
    "utc_datetime": "2021-04-29 12:34:56",
    "schema": {
        "title": "Object Information",
        "type": "object",
        "properties": {
            "name": {
                "title": "Object Name",
                "type": "text"
            }
        }
    },
    "data": {
        "name": {
            "_type": "text",
            "text": "Example Object"
        }
    }
}
Response JSON Object:
  • object_id (number) – the object’s ID

  • version_id (number) – the object version’s ID

  • action_id (number) – the action’s ID

  • action (object) – the action (if the parameter embed_action is set to a non-empty value)

  • user_id (number) – the ID of the user who created this version

  • user (object) – the user (if the parameter embed_user is set to a non-empty value)

  • utc_datetime (string) – the time and date when this version was created in UTC

  • schema (object) – the object’s schema

  • data (object) – the object’s data

  • data_diff (object) – the data difference between the specified and the previous version (if the parameter include_diff is set to a non-empty value)

Status Codes:

Creating a new object

POST /api/v1/objects/

Create a new object.

Example request:

POST /api/v1/objects/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Content-Type: application/json
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "action_id": 0,
    "schema": {
        "title": "Object Information",
        "type": "object",
        "properties": {
            "name": {
                "title": "Object Name",
                "type": "text"
            }
        }
    },
    "data": {
        "name": {
            "_type": "text",
            "text": "Example Object"
        }
    }
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/objects/1/versions/0
Request JSON Object:
  • version_id (number) – the object version’s ID (optional, must be 0)

  • action_id (number) – the action’s ID

  • schema (object) – the object’s schema (optional, must equal current action’s schema)

  • data (object) – the object’s data

Status Codes:

Updating an object / Creating a new object version

POST /api/v1/objects/(int: object_id)/versions/

Create a new version of an object (object_id).

Example request:

POST /api/v1/objects/1/versions/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Content-Type: application/json
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "data": {
        "name": {
            "_type": "text",
            "text": "Example Object"
        }
    }
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/objects/1/versions/1
Request JSON Object:
  • object_id (number) – the object’s ID (optional, must equal object_id in URL)

  • version_id (number) – the object version’s ID (optional, must equal new version’s ID)

  • action_id (number) – the action’s ID (optional, must equal previous action_id)

  • schema (object) – the object’s schema (optional, must equal previous schema or current action’s schema)

  • data (object) – the object’s data (either data or data_diff must be set)

  • data_diff (object) – the difference between the previous version and the new one (either data or data_diff must be set)

Status Codes:

Object Permissions

Reading whether an object is readable by all authenticated users

GET /api/v1/objects/(int: object_id)/permissions/public

Get whether or not an object is readable by all authenticated users.

Example request:

GET /api/v1/objects/1/permissions/public HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

true
Status Codes:

Setting whether an object is readable by all authenticated users

PUT /api/v1/objects/(int: object_id)/permissions/public

Set whether or not an object should be readable by all authenticated users.

Example request:

PUT /api/v1/objects/1/permissions/public HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

false

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

false
Status Codes:

Getting the permissions for all authenticated users

GET /api/v1/objects/(int: object_id)/permissions/authenticated_users

Get the permissions for an object for all authenticated users.

Example request:

GET /api/v1/objects/1/permissions/authenticated_users HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"none"
Status Codes:

Setting the permissions for all authenticated users

PUT /api/v1/objects/(int: object_id)/permissions/authenticated_users

Set the permissions for an object for all authenticated users.

Example request:

PUT /api/v1/objects/1/permissions/authenticated_users HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

"read"

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"read"
Status Codes:

Getting the permissions for anonymous users

GET /api/v1/objects/(int: object_id)/permissions/anonymous_users

Get the permissions for an object for anonymous users, if anonymous users are enabled.

Example request:

GET /api/v1/objects/1/permissions/anonymous_users HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"none"
Status Codes:

Setting the permissions for anonymous users

PUT /api/v1/objects/(int: object_id)/permissions/anonymous_users

Set the permissions for an object for anonymous users, if anonymous users are enabled.

Example request:

PUT /api/v1/objects/1/permissions/anonymous_users HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

"read"

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"read"
Status Codes:

Reading all users’ permissions

GET /api/v1/objects/(int: object_id)/permissions/users/

Get a mapping of user IDs to their permissions.

Example request:

GET /api/v1/objects/1/permissions/users/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "1": "read",
    "2": "grant"
}
Query Parameters:
  • include_instrument_responsible_users – If given, permissions from being an instrument responsible user will be included (optional)

  • include_groups – If given, permissions from basic group memberships will be included (optional)

  • include_projects – If given, permissions from project group memberships will be included (optional)

  • include_admins – If given, permissions from being an administrator will be included (optional)

Status Codes:

Reading a user’s permissions

GET /api/v1/objects/(int: object_id)/permissions/users/(int: user_id)

Get the permissions of a user for an object.

Example request:

GET /api/v1/objects/1/permissions/users/2 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"grant"
Query Parameters:
  • include_instrument_responsible_users – If given, permissions from being an instrument responsible user will be included (optional)

  • include_groups – If given, permissions from basic group memberships will be included (optional)

  • include_projects – If given, permissions from project group memberships will be included (optional)

  • include_admins – If given, permissions from being an administrator will be included (optional)

Status Codes:

Setting a user’s permissions

PUT /api/v1/objects/(int: object_id)/permissions/users/(int: user_id)

Set the permissions of a user for an object.

Example request:

PUT /api/v1/objects/1/permissions/users/2 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

"write"

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"write"
Status Codes:
  • 200 OK – no error

  • 400 Bad Request – invalid data (should be “read”, “write”, “grant” or “none”)

  • 403 Forbidden – the user does not have GRANT permissions for this object

  • 404 Not Found – the object or user does not exist

Reading all basic groups’ permissions

GET /api/v1/objects/(int: object_id)/permissions/groups/

Get a mapping of basic group IDs to their permissions.

Example request:

GET /api/v1/objects/1/permissions/groups/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "4": "write"
}
Query Parameters:
  • include_projects – If given, permissions from project group memberships will be included (optional)

Status Codes:

Reading a basic group’s permissions

GET /api/v1/objects/(int: object_id)/permissions/groups/(int: group_id)

Get the permissions of a basic group for an object.

Example request:

GET /api/v1/objects/1/permissions/groups/4 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"write"
Query Parameters:
  • include_projects – If given, permissions from project group memberships will be included (optional)

Status Codes:

Setting a basic group’s permissions

PUT /api/v1/objects/(int: object_id)/permissions/groups/(int: group_id)

Set the permissions of a basic group for an object.

Example request:

PUT /api/v1/objects/1/permissions/groups/2 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

"read"

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"read"
Status Codes:
  • 200 OK – no error

  • 400 Bad Request – invalid data (should be “read”, “write”, “grant” or “none”)

  • 403 Forbidden – the user does not have GRANT permissions for this object

  • 404 Not Found – the object or basic group does not exist

Reading all project groups’ permissions

GET /api/v1/objects/(int: object_id)/permissions/projects/

Get a mapping of project group IDs to their permissions.

Example request:

GET /api/v1/objects/1/permissions/projects/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "7": "read"
}
Status Codes:

Reading a project group’s permissions

GET /api/v1/objects/(int: object_id)/permissions/projects/(int: project_id)

Get the permissions of a project group for an object.

Example request:

GET /api/v1/objects/1/permissions/projects/7 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"read"
Status Codes:

Setting a project group’s permissions

PUT /api/v1/objects/(int: object_id)/permissions/projects/(int: project_id)

Set the permissions of a project group for an object.

Example request:

PUT /api/v1/objects/1/permissions/projects/2 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

"read"

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

"read"
Status Codes:
  • 200 OK – no error

  • 400 Bad Request – invalid data (should be “read”, “write”, “grant” or “none”)

  • 403 Forbidden – the user does not have GRANT permissions for this object

  • 404 Not Found – the object or project group does not exist

Instruments

Reading a list of all instruments

GET /api/v1/instruments/

Get a list of all instruments.

Example request:

GET /api/v1/instruments/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "instrument_id": 1,
        "name": "Example Instrument",
        "description": "This is an example instrument",
        "is_hidden": false,
        "instrument_scientists": [1, 42],
        "location_id": null
    }
]
Status Codes:

Reading an instrument

GET /api/v1/instruments/(int: instrument_id)

Get the specific instrument (instrument_id).

Example request:

GET /api/v1/instruments/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "instrument_id": 1,
    "name": "Example Instrument",
    "description": "This is an example instrument",
    "is_hidden": false,
    "instrument_scientists": [1, 42],
    "location_id": 1
}
Response JSON Object:
  • instrument_id (number) – the instrument’s ID

  • name (string) – the instruments’s name

  • description (string) – the instruments’s description

  • is_hidden (bool) – whether or not the instrument is hidden

  • instrument_scientists (list) – the instrument scientists’ IDs

  • location_id (number) – the instrument location’s ID

Status Codes:

Instrument Log Entries

Reading a list of all log entries for an instrument

GET /api/v1/instruments/(int: instrument_id)/log_entries/

Get a list of all log entries for a specific instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "log_entry_id": 1,
        "author": 1,
        "versions": [
            {
                "log_entry_id": 1,
                "version_id": 1,
                "utc_datetime": "2020-08-19T12:13:14.123456",
                "content": "Example Log Entry 1",
                "categories": [],
                "event_utc_datetime": "2020-08-03T12:13:14.000000",
                "content_is_markdown": false
            }
        ]
    },
    {
        "log_entry_id": 2,
        "author": 1,
        "versions": [
            {
                "log_entry_id": 2,
                "version_id": 1,
                "utc_datetime": "2020-08-19T13:14:15.123456",
                "content": "Example Log Entry 2",
                "categories": [
                    {
                        "category_id": 1,
                        "title": "Error Report"
                    },
                    {
                        "category_id": 7,
                        "title": "Maintenance Log"
                    }
                ],
                "event_utc_datetime": null,
                "content_is_markdown": false
            }
        ]
    }
]
Status Codes:

Reading an instrument log entry

GET /api/v1/instruments/(int: instrument_id)/log_entries/(int: log_entry_id)

Get the specific log entry (log_entry_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries/2 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "log_entry_id": 2,
    "author": 1,
    "versions": [
        "log_entry_id": 2,
        "version_id": 1,
        "utc_datetime": "2020-08-19T13:14:15.123456",
        "content": "Example Log Entry 2",
        "categories": [
            {
                "category_id": 1,
                "title": "Error Report"
            },
            {
                "category_id": 7,
                "title": "Maintenance Log"
            }
        ],
        "event_utc_datetime": "2020-08-03T12:13:14.123456",
        "content_is_markdown": false
    ]
}
Response JSON Object:
  • log_entry_id (number) – the log entry’s ID

  • author (number) – the user ID of the log entry’s author

  • versions (list) – an array of versions of the log entry

  • versions[?].log_entry_id (number) – the log entry’s ID

  • versions[?].version_id (number) – the log entry version’s ID

  • versions[?].utc_datetime (string) – the date and time of the log entry version in UTC in ISO format

  • versions[?].content (string) – the log entry version’s content

  • versions[?].categories (list) – the log entry version’s categories

  • versions[?].event_utc_datetime (string) – the date and time of the event in UTC in ISO format if set, else null

  • versions[?].content_is_markdown (string) – whether the log entry version’s content is markdown

Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument or the log entry do not exist

Reading a list of all log categories for an instrument

GET /api/v1/instruments/(int: instrument_id)/log_categories/

Get a list of all log categories for a specific instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_categories HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "category_id": 1,
        "title": "Error Report"
    },
    {
        "category_id": 7,
        "title": "Maintenance Log"
    }
]
Status Codes:

Reading an instrument log category

GET /api/v1/instruments/(int: instrument_id)/log_categories/(int: category_id)

Get the specific log category (category_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_categories/7 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "category_id": 7,
    "title": "Maintenance Log"
}
Response JSON Object:
  • category_id (number) – the log category’s ID

  • title (string) – the log category’s title

Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument or the log category do not exist

Reading a list of all file attachments for a log entry

GET /api/v1/instruments/(int: instrument_id)/log_entries/(int: log_entry_id)/file_attachments/

Get a list of file attachments for a specific log entry (log_entry_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries/2/file_attachments HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "file_attachment_id": 1,
        "file_name": "example.txt",
        "content": "RXhhbXBsZSBDb250ZW50"
    }
]
Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument or the log entry do not exist

Reading a file attachment for a log entry

GET /api/v1/instruments/(int: instrument_id)/log_entries/(int: log_entry_id)/file_attachments/(int: file_attachment_id)

Get a specific file attachment (file_attachment_id) for a log entry (log_entry_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries/2/file_attachments/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "file_attachment_id": 1,
    "file_name": "example.txt",
    "content": "RXhhbXBsZSBDb250ZW50"
}
Response JSON Object:
  • file_attachment_id (string) – the file attachment’s ID

  • file_name (string) – the original file name

  • content (string) – the base64 encoded file content

Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument, the log entry or the file attachment do not exist

Reading a list of all object attachments for a log entry

GET /api/v1/instruments/(int: instrument_id)/log_entries/(int: log_entry_id)/object_attachments/

Get a list of object attachments for a specific log entry (log_entry_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries/2/object_attachments HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "object_attachment_id": 1,
        "object_id": 1
    }
]
Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument or the log entry do not exist

Reading an object attachment for a log entry

GET /api/v1/instruments/(int: instrument_id)/log_entries/(int: log_entry_id)/object_attachments/(int: object_attachment_id)

Get a specific object attachment (object_attachment_id) for a log entry (log_entry_id) for an instrument (instrument_id).

Example request:

GET /api/v1/instruments/1/log_entries/2/object_attachments/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "object_attachment_id": 1,
    "object_id": 1
}
Response JSON Object:
  • object_attachment_id (string) – the object attachment’s ID

  • object_id (string) – the object ID

Status Codes:
  • 200 OK – no error

  • 403 Forbidden – the instrument log can only be accessed by instrument scientists

  • 404 Not Found – the instrument, the log entry or the object attachment do not exist

Creating an instrument log entry

POST /api/v1/instruments/(int: instrument_id)/log_entries/

Create a log entry for an instrument (instrument_id) and optionally attach files and objects to it.

Example request:

POST /api/v1/instruments/1/log_entries/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "content": "Example Log Entry Text",
    "category_ids": [1, 7],
    "file_attachments": [
        {
            "file_name": "example.txt",
            "base64_content": "RXhhbXBsZSBDb250ZW50"
        }
    ],
    "object_attachments": [
        {
            "object_id": 1
        },
        {
            "object_id": 2
        }
    ]
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: https://iffsamples.fz-juelich.de/api/v1/instruments/1/log_entries/1
Request JSON Object:
  • content (string) – the log entry’s content

  • category_ids (list) – an optional list of category IDs for the log entry

  • file_attachments (list) – an optional list of file attachments as json objects with file_name and base64_content attributes

  • object_attachments (list) – an optional list of object attachments as json objects with an object_id attribute

Status Codes:
  • 201 Created – the log entry and optional attachments have been created successfully

  • 400 Bad Request – there was an error in the given json data

  • 403 Forbidden – only instrument scientists can write to the instrument log

  • 404 Not Found – the instrument does not exist

Actions

Reading a list of all actions

GET /api/v1/actions/

Get a list of all actions.

Example request:

GET /api/v1/actions/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "action_id": 1,
        "instrument_id": null,
        "user_id": null,
        "type": "sample",
        "type_id": -99,
        "name": "Example Sample Creation",
        "description": "This is an example action",
        "is_hidden": false,
        "schema": {
            "title": "Example Sample",
            "type": "object",
            "properties": {
                "name": {
                    "title": "Sample Name",
                    "type": "text"
                }
            },
            "required": ["name"]
        }
    },
    {
        "action_id": 2,
        "instrument_id": 1,
        "user_id": null,
        "type": "measurement",
        "type_id": -98,
        "name": "Example Measurement",
        "description": "This is an example action",
        "is_hidden": false,
        "schema": {
            "title": "Example Measurement",
            "type": "object",
            "properties": {
                "name": {
                    "title": "Measurement Name",
                    "type": "text"
                }
            },
            "required": ["name"]
        }
    }
]
Status Codes:

Reading an action

GET /api/v1/actions/(int: action_id)

Get the specific action (action_id).

Example request:

GET /api/v1/actions/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "action_id": 1,
    "instrument_id": null,
    "user_id": null,
    "type": "sample",
    "type_id": -99,
    "name": "Example Sample Creation",
    "description": "This is an example action",
    "is_hidden": false,
    "schema": {
        "title": "Example Sample",
        "type": "object",
        "properties": {
            "name": {
                "title": "Sample Name",
                "type": "text"
            }
        },
        "required": ["name"]
    }
}
Response JSON Object:
  • action_id (number) – the action’s ID

  • instrument_id (number) – the action’s instrument’s ID or null

  • user_id (number) – the action’s user ID, if it is a user-specific action, or null

  • type (string) – the action’s type (“sample”, “measurement”, “simulation” or “custom”)

  • type_id (number) – the ID of the action’s type

  • name (string) – the action’s name

  • description (string) – the action’s description

  • is_hidden (bool) – whether or not the action is hidden

  • schema (object) – the action’s schema

Status Codes:

Updating an action

POST /api/v1/actions/(int: action_id)

Update the specific action (action_id).

Example request:

POST /api/v1/actions/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "action_id": 1,
    "instrument_id": null,
    "user_id": null,
    "type": "sample",
    "type_id": -99,
    "name": "Example Sample Creation",
    "description": "This is an example action",
    "is_hidden": false,
    "schema": {
        "title": "Example Sample",
        "type": "object",
        "properties": {
            "name": {
                "title": "Sample Name",
                "type": "text"
            }
        },
        "required": ["name"]
    }
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "action_id": 1,
    "instrument_id": null,
    "user_id": null,
    "type": "sample",
    "type_id": -99,
    "name": "Example Sample Creation",
    "description": "This is an example action",
    "is_hidden": false,
    "schema": {
        "title": "Example Sample",
        "type": "object",
        "properties": {
            "name": {
                "title": "Sample Name",
                "type": "text"
            }
        },
        "required": ["name"]
    }
}
Request JSON Object:
  • name (string) – the action’s name

  • description (string) – the action’s description

  • is_hidden (bool) – whether or not the action is hidden

  • schema (object) – the action’s schema

  • action_id (number) – the action’s ID (optional, must not be changed)

  • instrument_id (number) – the action’s instrument’s ID or null (optional, must not be changed)

  • user_id (number) – the action’s user ID, if it is a user-specific action, or null (optional, must not be changed)

  • type (string) – the action’s type (“sample”, “measurement”, “simulation” or “custom”, optional, must not be changed)

  • type_id (number) – the ID of the action’s type (optional, must not be changed)

Status Codes:

Action Types

Reading a list of all action types

GET /api/v1/action_types/

Get a list of all action types.

Example request:

GET /api/v1/action_types/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "type_id": -99,
        "name": "Sample Creation",
        "object_name": "sample",
        "admin_only": false
    },
    {
        "type_id": -98,
        "name": "Measurement",
        "object_name": "measurement",
        "admin_only": false
    },
    {
        "type_id": -97,
        "name": "Simulation",
        "object_name": "simulation",
        "admin_only": false
    }
]
Status Codes:

Reading an action type

GET /api/v1/action_types/(int: type_id)

Get the specific action type (type_id).

Example request:

GET /api/v1/action_types/-99 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "type_id": -99,
    "name": "Sample Creation",
    "object_name": "sample",
    "admin_only": false
}
Response JSON Object:
  • type_id (number) – the action type’s ID

  • name (string) – the action type’s name

  • object_name (string) – the name of objects created with this action type

  • admin_only (bool) – whether or not actions with this type can only be created by administrators

Status Codes:

Users

Reading a list of all users

GET /api/v1/users/

Get a list of all users.

Example request:

GET /api/v1/users/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "user_id": 1,
        "name": "Example User",
        "orcid": null,
        "affiliation": null,
        "role": null
    }
]
Status Codes:

Reading a user

GET /api/v1/users/(int: user_id)

Get the specific user (user_id).

Example request:

GET /api/v1/users/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "user_id": 1,
    "name": "Example User",
    "orcid": null,
    "affiliation": null,
    "role": null
}
Response JSON Object:
  • user_id (number) – the user’s ID

  • name (string) – the user’s name

  • orcid (string) – the user’s ORCid ID (optional)

  • affiliation (string) – the user’s affiliation (optional)

  • role (string) – the user’s role (optional)

  • email (string) – the user’s email (only for API requests by administrators)

Status Codes:

Reading the current user

GET /api/v1/users/me

Get the current user.

Example request:

GET /api/v1/users/me HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "user_id": 1,
    "name": "Example User",
    "orcid": null,
    "affiliation": null,
    "role": null
}
Response JSON Object:
  • user_id (number) – the user’s ID

  • name (string) – the user’s name

  • orcid (string) – the user’s ORCid ID (optional)

  • affiliation (string) – the user’s affiliation (optional)

  • role (string) – the user’s role (optional)

  • email (string) – the user’s email (only for API requests by administrators)

Status Codes:

Locations

Reading a list of all locations

GET /api/v1/locations/

Get a list of all locations.

Example request:

GET /api/v1/locations/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "location_id": 1,
        "name": "Example Location",
        "description": "This is an example location",
        "parent_location_id": null,
        "type_id": -99,
        "is_hidden": false
    }
]
Status Codes:

Reading a location

GET /api/v1/locations/(int: location_id)

Get the specific location (location_id).

Example request:

GET /api/v1/locations/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "location_id": 1,
    "name": "Example Location",
    "description": "This is an example location",
    "parent_location_id": null,
    "type_id": -99,
    "is_hidden": false
}
Response JSON Object:
  • location_id (number) – the location’s ID

  • name (string) – the locations’s name

  • description (string) – the locations’s description

  • parent_location_id (number) – the parent location’s ID

  • type_id (number) – the location type’s ID

  • is_hidden (bool) – whether or not the location is hidden

Status Codes:

Reading a list of an object’s locations

GET /api/v1/objects/(int: object_id)/locations/

Get a list of all object locations assignments for a specific object (object_id).

Example request:

GET /api/v1/objects/1/locations/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "object_id": 1,
        "location_id": 3,
        "responsible_user_id": 6,
        "user_id": 17,
        "description": "Shelf C",
        "utc_datetime": "2018-12-11 17:50:00"
    }
]
Status Codes:

Reading an object’s location

GET /api/v1/objects/(int: object_id)/locations/(int: index)

Get a specific object location assignment (index) for a specific object (object_id).

Example request:

GET /api/v1/objects/1/locations/0 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "object_id": 1,
    "location_id": 3,
    "responsible_user_id": 6,
    "user_id": 17,
    "description": "Shelf C",
    "utc_datetime": "2018-12-11 17:50:00"
}
Response JSON Object:
  • object_id (number) – the object’s ID

  • location_id (number) – the location’s ID

  • responsible_user_id (number) – the ID of the user who is responsible for the object

  • user_id (number) – the ID of the user who assigned this location to the object

  • description (string) – the description of the object’s position

  • utc_datetime (number) – the datetime when the object was stored

Status Codes:
  • 200 OK – no error

  • 404 Not Found – the object or the object location assignment does not exist

Location Types

Reading a list of all location types

GET /api/v1/location_types/

Get a list of all location types.

Example request:

GET /api/v1/location_types/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "location_type_id": 1,
        "name": "Example Location Type"
    }
]
Status Codes:

Reading a location type

GET /api/v1/location_types/(int: location_type_id)

Get the specific location type (location_type_id).

Example request:

GET /api/v1/location_types/1 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "location_type_id": 1,
    "name": "Example Location Type"
}
Response JSON Object:
  • location_type_id (number) – the location type’s ID

  • name (string) – the location type’s name

Status Codes:

Files

Reading a list of an object’s files

GET /api/v1/objects/(int: object_id)/files/

Get a list of all files for a specific object (object_id).

Example request:

GET /api/v1/objects/1/files/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "object_id": 1,
        "file_id": 0,
        "storage": "url",
        "url": "https://iffsamples.fz-juelich.de"
    }
]
Status Codes:

Reading information for a file

GET /api/v1/objects/(int: object_id)/files/(int: file_id)

Get a specific file (file_id) for a specific object (object_id).

Example request:

GET /api/v1/objects/1/files/0 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "object_id": 1,
    "file_id": 0,
    "storage": "url",
    "url": "https://iffsamples.fz-juelich.de"
}
Response JSON Object:
  • object_id (number) – the object’s ID

  • file_id (number) – the file’s ID

  • storage (string) – how the file is stored (local, database or url)

  • url (string) – the URL of the file (for url storage)

  • original_file_name (string) – the original name of the file (for local or database storage)

  • base64_content (string) – the base64 encoded content of the file (for local or database storage)

  • hash (object) – hash algorithm and hexdigest of the content (optional, for local, database or local_reference storage)

Status Codes:

Uploading a file

POST /api/v1/objects/(int: object_id)/files/

Create a new file with database storage for a specific object (object_id).

Example request:

POST /api/v1/objects/1/files/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "storage": "database",
    "original_file_name": "test.txt",
    "base64_content": "dGVzdA==",
    "hash": {
        "algorithm": "sha256",
        "hexdigest": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
    }
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: https://iffsamples.fz-juelich.de/api/v1/objects/1/files/0
Request JSON Object:
  • storage (string) – how the file is stored (either database or local_reference)

  • original_file_name (string) – the original name of the file

  • base64_content (string) – the base64 encoded content of the file

  • hash (object) – hash algorithm and hexdigest of the content (optional)

Status Codes:

Comments

Reading a list of an object’s comments

GET /api/v1/objects/(int: object_id)/comments/

Get a list of all comments for a specific object (object_id).

Example request:

GET /api/v1/objects/1/comments/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "object_id": 1,
        "user_id": 1,
        "comment_id": 0,
        "content": "This is an example comment"
        "utc_datetime": "2020-12-03T01:02:03.456789"
    }
]
Status Codes:

Reading information for a comment

GET /api/v1/objects/(int: object_id)/comments/(int: comment_id)

Get a specific comment (comment_id) for a specific object (object_id).

Example request:

GET /api/v1/objects/1/comments/0 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "object_id": 1,
    "user_id": 1,
    "comment_id": 0,
    "content": "This is an example comment"
    "utc_datetime": "2020-12-03T01:02:03.456789"
}
Response JSON Object:
  • object_id (number) – the object’s ID

  • user_id (number) – the ID of the user who posted the comment

  • comment_id (number) – the comment’s ID

  • content (string) – the comment’s content

  • utc_datetime (string) – the time the comment was posted in UTC formatted in ISO 8601 format

Status Codes:

Posting a comment

POST /api/v1/objects/(int: object_id)/comments/

Create a new comment for a specific object (object_id).

Example request:

POST /api/v1/objects/1/comments/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "content": "This is an example comment"
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: https://iffsamples.fz-juelich.de/api/v1/objects/1/comments/0
Request JSON Object:
  • content (string) – the (non-empty) content for the new comment

Status Codes:

Object Data Diff Syntax

When updating object data, instead of providing the full object data a diff can be provided instead. This is an alternative to downloading the current object version, performing the change locally and then uploading the data again, and can be useful in scripts, e.g. to update the status of an object.

The syntax for these diffs is specific to SampleDB data entries, but fairly simple:

  • When comparing arrays, the diff is a list that contains the diff item by item, or null if the items are the same.

  • When comparing objects, the diff is a dictionary mapping each key to the diff of the values, if they have changed.

  • Otherwise, the diff is a dictionary mapping the key _before to the value before the change (if there was any data there before) and mapping the key _after to the value after the change (unless there is no value afterwards).

As an example, considering the following data before:

{
  "name": {
      "_type": "text",
      "text": {
          "en": "Example Measurement"
      }
  },
  "measurement_complete": {
      "_type": "bool",
      "value": false
  },
  "mass_list": [
    {
      "_type": "quantity",
      "magnitude": 10,
      "magnitude_in_base_units": 0.01,
      "units": "g",
      "dimensionality": "[mass]"
    }
  ]
}

The following diff would add a value of 11g to mass_list and set measurement_complete to True:

{
  "measurement_complete": {
    "_before": {
      "_type": "bool",
      "value": false
    },
    "_after": {
      "_type": "bool",
      "value": true
    }
  },
  "mass_list": [
    null,
    {
      "_after": {
        "_type": "quantity",
        "magnitude": 11,
        "magnitude_in_base_units": 0.011,
        "units": "g",
        "dimensionality": "[mass]"
      }
    }
  ]
}

A dictionary mapping indices to item diffs is also supported for arrays, though this syntax will not be generated by SampleDB. Indices are strings, with signed string indices (e.g. “+0” or “-1”) being relative to the end of the array. This can be useful for writing diffs that change arrays without requiring knowledge about the current array length. As such, the following diff would also add an entry to mass_list, using this alternative array index syntax:

{
  "mass_list": {
    "+0": {
      "_after": {
        "_type": "quantity",
        "magnitude": 12,
        "magnitude_in_base_units": 0.012,
        "units": "g",
        "dimensionality": "[mass]"
      }
    }
  }
}

While diffs for timeseries will use the generic _before and _after syntax when produced by SampleDB, using the array or array index syntax for timeseries is also supported when providing diffs via the HTTP API. As such, the following two diffs would both append an entry to the timeseries temperature:

{
  "temperature": [
    null,
    null,
    {
      "_after": ["2023-01-02 03:04:05.678900", 20, 293,15]
    }
  ]
}
{
  "temperature": {
    "+0": {
      "_after": ["2023-01-02 03:04:05.678900", 20, 293,15]
    }
  }
}

Access Tokens

In some situations, e.g. for interactive applications that use the API, users may want to authenticate with their username and password, but these should not be stored. In these situations, access tokens are a short-lived and more convenient alternative to having the users create API tokens. An access token can be used with Bearer authentication, just like an API token. After a given time this access token will expire automatically, so that there won’t be any cleanup needed by the user. When creating an access token, the expiration date and time (in UTC) will be returned along with a refresh token, which can be used to create a new access token to avoid expiry, as long as the access token is needed.

POST /api/v1/access_tokens/

Create a new access token.

Example request:

POST /api/v1/access_tokens/ HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

{
    "description": "Access Token for Instrument Control"
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

{
    "access_token": "d0305fdf89d737dfa3062569022ef38be363b8fdf3d4137d26674809e34eac5a",
    "refresh_token": "b6f6d66d6ee92b4bc38857aabab793c2eb1e982941fa576b02b0535c280498c3",
    "expiration_utc_datetime": "2023-04-05 06:07:08"
    "description": "Access Token for Instrument Control"
}
Request JSON Object:
  • description (string) – a description for the access token

Response JSON Object:
  • access_token (string) – the created access token

  • refresh_token (string) – the accompanying refresh token

  • expiration_utc_datetime (string) – the expiration date and time (in UTC)

  • description (string) – the given description

Status Codes:
  • 201 Created – the access token has been created successfully

Object Log Entries

Reading the full accessible object log

GET /api/v1/object_log_entries/

Get a list of all object log entries for objects with at least read permission.

Example request:

GET /api/v1/object_log_entries/?after_id=3514 HTTP/1.1
Host: iffsamples.fz-juelich.de
Accept: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "log_entry_id": 3515,
        "type": "CREATE_OBJECT",
        "object_id": 163,
        "user_id": 12,
        "data": {},
        "utc_datetime": "2023-12-03 01:02:03",
        "is_imported": false
    }
]
Request JSON Object:
  • after_id (number) – only log entries created after the entry with the id after_id are returned (optional)

Response JSON Object:
  • log_entry_id (number) – the log entry’s ID

  • type (string) – the type of the log entry

  • object_id (number) – the ID of the object this log entry is related to

  • user_id (string) – the ID of the user by whose activity the log entry was created

  • data (string) – the data of the log entry, might be empty ({})

  • utc_datetime (string) – the timestamp of the log entry in UTC in format %Y-%m-%d %H:%M:%S

  • is_imported (bool) – whether the log entry was imported

Status Codes: