Skip to main content

sherlock-api

Python client for the Sherlock REST API. Build your own Sherlock applications — create cases and batches, upload inspection images with measurements, write log entries, and drive modal dialogs and notifications in a running Sherlock process.

Install

pip install sherlock-api

Requires Python 3.10+.

Quickstart

from PIL import Image
from sherlock_api import (
    SherlockAPIClient,
    CreateCaseRequest,
    CreateBatchRequest,
    RobotPlatform,
    DecisionClass,
)

with SherlockAPIClient(sherlock_port=8080) as client:
    case = client.post_case(
        CreateCaseRequest(
            "Bushing inspection",
            RobotPlatform.UNIVERSAL_ROBOTS,
            "0A0E012F7772596B03D92AAA544763BB",
        )
    )
    batch = client.post_batch(CreateBatchRequest(case["id"], "Batch 1"))

    image, measurements = client.upload_image_with_measurements(
        Image.open("part.png"),
        "part.png",
        DecisionClass.Ok,
        [("diameter_mm", 12.04), ("roundness", 0.98)],
        batch["id"],
    )

    client.log_batch_info(batch["id"], f"Uploaded {image['image_name']}")

Configuration

Every constructor argument falls back to an environment variable. A script launched by Sherlock gets these for free, so SherlockAPIClient() with no arguments is usually all you need:

Argument Environment variable Default
sherlock_url SHERLOCK_URL http://localhost
sherlock_port SHERLOCK_PORT — (required)
sherlock_process_id SHERLOCK_PROCESS_ID None
sherlock_case_id SHERLOCK_CASE_ID None
sherlock_batch_id SHERLOCK_BATCH_ID None

The three id defaults are used whenever you omit the corresponding argument — client.get_case() reads sherlock_case_id, client.get_batch() reads sherlock_batch_id, and the process methods read sherlock_process_id. Omitting an argument that has no default raises SherlockConfigurationError.

Keyword-only options: request_timeout (seconds, default 30.0), max_retries (default 3, applied to connection errors and 502/503/504 on GET and DELETE), and session to supply your own requests.Session.

Modal dialogs

post_modal returns a modal id; get_modal long-polls for the operator's answer and returns DialogResult.NoResponse if the poll expires. Its timeout is in milliseconds and is enforced by the server — the client timeout is widened automatically to outlast it.

from sherlock_api import (
    CreateProcessModalDialogRequest,
    DialogType,
    DialogResult,
    Language,
)

modal_id = client.post_modal(
    CreateProcessModalDialogRequest(DialogType.YesNo, Language.English, "Part looks OK?")
)

result = client.get_modal(modal_id, timeout=30_000)
if result is DialogResult.NoResponse:
    client.delete_modal(modal_id)

Notifications

from sherlock_api import CreateNotificationRequest, NotificationAttachment

client.post_notification(
    CreateNotificationRequest(
        "Batch finished",
        "42 parts inspected, 3 rejected.",
        [NotificationAttachment("report.pdf", "application/pdf", pdf_bytes)],
    )
)

A notification sent to a process that no longer exists is logged as a warning on the sherlock_api.client logger rather than raised — it is fire-and-forget.

API surface

Area Methods
Files get_file, post_file, post_file_from_memory
Cases get_cases, get_case, post_case
Batches get_batch, get_batches_for_case, post_batch
Images get_image, get_images_for_batch, post_image, upload_image, upload_image_with_measurement, upload_image_with_measurements
Logs get_log, post_log, log_{case,batch,image}_{error,warning,info}
Measurements get_measurement, post_measurement, delete_measurement
Processes get_process_state, is_process_running, get_env_state, get_env_vars, post_modal, get_modal, delete_modal, post_notification

Methods returning JSON return the parsed dict or list from the server as-is.

Errors

SherlockError
├── SherlockConfigurationError   (also a ValueError)  missing port or id
└── SherlockAPIError             (also a RuntimeError) unexpected HTTP status
    ├── SherlockBadRequestError  400
    ├── SherlockNotFoundError    404
    ├── SherlockTimeoutError     408
    └── SherlockServerError      5xx

SherlockAPIError carries .status_code, .reason, .body (truncated to 500 characters), .method and .url.

from sherlock_api import SherlockNotFoundError

try:
    client.get_case("0" * 32)
except SherlockNotFoundError as err:
    print(err.status_code, err.url)

Network-level failures (requests.ConnectionError, requests.Timeout) propagate from requests unchanged.

Logging

The library logs to the sherlock_api logger and attaches a NullHandler, so it stays silent until your application configures logging:

import logging

logging.basicConfig(level=logging.INFO)

Development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

pytest            # offline, no Sherlock server needed
ruff check .
mypy src/

examples/smoke_check.py exercises the process endpoints against a live Sherlock instance.

License

Apache-2.0. See LICENSE.

Release files for sherlock-api 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sherlock-api 0.1.0
File Size Uploaded
sherlock_api-0.1.0.tar.gz 23.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sherlock-api 0.1.0
File Interpreter ABI Platform
sherlock_api-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.1 kB

Release files / sherlock_api-0.1.0.tar.gz

Download URL sherlock_api-0.1.0.tar.gz
Size 23.3 kB
Tags Source
SHA-256 checksum
How to use checksums
1db9b2c432511bdb193af7b083826d340248b2e1cd5324542a7f0bf5edd33bd9
BLAKE2b-256 checksum
How to use checksums
3a2df072fce9c61cf1c988d5d50d6feb1b809969a2810c8bc5d1306f32805482
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / sherlock_api-0.1.0-py3-none-any.whl

Download URL sherlock_api-0.1.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe715684930d352cec3b715029e61c2864902f3d3ba427f5d4102590ff43aac3
BLAKE2b-256 checksum
How to use checksums
1cb04d397af5f31542a6e1d98f92dd7dc1099a51560ba13e473de9b66e5e1a2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page