Skip to content

STOW-RS — Store Instances

The Store transaction (PS3.18 §10.5) uses the POST method to store representations of studies, series, and instances contained in the request payload.

Method Path Description
POST /studies Store instances
POST /studies/{study} Store instances for a specific study

The study path parameter corresponds to the DICOM attribute StudyInstanceUID (0020,000D). When it is specified, any instance in the payload that does not belong to that study is reported as a failure with failure reason 272 (PS3.18 §6.6.1.2).

Authorization

Store requests are not subject to viewer-token authorization, even when it is enabled for the read interfaces. See JWT Authorization.

Request

Content-Type

The request payload must use one of the following Content-Type headers:

  • multipart/related; type="application/dicom" — one part per DICOM instance; use this to store multiple instances in one request
  • application/dicom — a single DICOM instance

A multipart/related payload that names no boundary results in 500 (Internal Server Error).

Required instance attributes

Each DICOM file must be parseable as a DICOM Part 10 file, and the following elements must be present:

Tag Attribute
(0020,000D) StudyInstanceUID
(0020,000E) SeriesInstanceUID
(0008,0018) SOPInstanceUID
(0002,0010) TransferSyntaxUID

Notes:

  • SOPClassUID (0008,0016) is extracted on a best-effort basis; instances lacking it are still accepted
  • No UID format or length validation is performed beyond presence checks
  • Files that fail parsing or are zero-length are reported in the FailedSOPSequence with failure reason 272

Ingest-time transcoding

Unlike a pass-through store, the service may transcode pixel data at ingest time according to rules evaluated against the instance's metadata (modality, transfer syntax, frame parameters such as bits allocated/stored, rows, columns, and photometric interpretation).

By default, instances of modalities CR, CT, DX, MG, and MR — and losslessly-encoded NM, OT, PT, RF, SM, and US instances — are transcoded to High-Throughput JPEG 2000 with RPCL Options (Lossless Only, 1.2.840.10008.1.2.4.202). All other DICOM attributes are stored as provided. See Transfer syntax support for the full list of recognized transfer syntaxes and the rule table.

Transcoding can be disabled per request with the header:

Header Accepted values Description
x-kastoria-disable-transcode true Store instances in their original transfer syntax without transcoding

Response

Responses are always returned as application/dicom+json, populated as a DICOM dataset with the following elements:

Tag Name Description
(0008,1190) RetrieveURL The retrieve URL of the study, if StudyInstanceUID was provided and at least one instance was stored successfully
(0008,1198) FailedSOPSequence The sequence of instances that failed to store
(0008,1199) ReferencedSOPSequence The sequence of stored instances

Each dataset in FailedSOPSequence has the following elements:

Tag Name Description
(0008,1150) ReferencedSOPClassUID The SOP class UID of the instance that failed to store
(0008,1155) ReferencedSOPInstanceUID The SOP instance UID of the instance that failed to store
(0008,1197) FailureReason The reason code why this instance failed to store

Each dataset in ReferencedSOPSequence has the following elements:

Tag Name Description
(0008,1150) ReferencedSOPClassUID The SOP class UID of the instance that was stored (omitted when unavailable)
(0008,1155) ReferencedSOPInstanceUID The SOP instance UID of the instance that was stored
(0008,1190) RetrieveURL The retrieve URL of this instance on the service

Retrieve URLs

RetrieveURL tags are omitted entirely when the base URL cannot be determined. The authoritative base URL for retrieval from the DICOMweb service is configured in the service deployment. As RetrieveURL is dereferenced by whoever receives it, it will never be built from an unverified request header.

If the base URL is not configured for a deployment, store responses from that service will carry no (0008,1190) at either level. The store itself still succeeds and the response is otherwise unchanged — the instances are stored and listed in the ReferencedSOPSequence, without a URL to fetch them back by.

For POST /studies (without a study UID in the path), the top-level study RetrieveURL is only included when all stored instances belong to a single study.

Failure reason codes

Code Description
272 (0x0110) Processing failure — used for all store failures, including parse failures, zero-length parts, storage errors, and instances whose StudyInstanceUID does not match the study UID stated in the request path

Status codes

Code Description
200 (OK) All the SOP instances in the request were stored successfully
202 (Accepted) Some instances were stored successfully, others failed. Details are in the response body
400 (Bad Request) The provided Content-Type is neither multipart/related nor application/dicom
409 (Conflict) None of the instances in the store transaction request were stored
500 (Internal Server Error) The server encountered an unexpected error, including a multipart/related Content-Type that names no boundary

Examples

Store a single instance

curl -X POST "http://localhost:3000/studies" \
  -H "Content-Type: application/dicom" \
  -H "Accept: application/dicom+json" \
  --data-binary @instance.dcm

Store multiple instances into a specific study

curl -X POST "http://localhost:3000/studies/1.2.840.113619.2.55.3.604688119.868.1234567890.1" \
  -H 'Content-Type: multipart/related; type="application/dicom"; boundary=BOUNDARYZ' \
  -H "Accept: application/dicom+json" \
  --data-binary $'--BOUNDARYZ\r\nContent-Type: application/dicom\r\nContent-Transfer-Encoding: binary\r\n\r\n' \
  --data-binary @file1.dcm \
  --data-binary $'\r\n--BOUNDARYZ\r\nContent-Type: application/dicom\r\nContent-Transfer-Encoding: binary\r\n\r\n' \
  --data-binary @file2.dcm \
  --data-binary $'\r\n--BOUNDARYZ--\r\n'

Successful response

All instances stored. The study-level RetrieveURL is present when the base URL is configured for the deployment:

{
  "00081190": { "vr": "UR", "Value": ["https://dicom.example.com/studies/1.2.840.113619.2.55.3.604688119.868.1234567890.1"] },
  "00081199": {
    "vr": "SQ",
    "Value": [
      {
        "00081150": { "vr": "UI", "Value": ["1.2.840.10008.5.1.4.1.1.2"] },
        "00081155": { "vr": "UI", "Value": ["1.2.840.113619.2.55.3.12345.1"] },
        "00081190": {
          "vr": "UR",
          "Value": [
            "https://dicom.example.com/studies/1.2.840.113619.2.55.3.604688119.868.1234567890.1/series/1.2.840.113619.2.55.3.604688119.868.1234567890.2/instances/1.2.840.113619.2.55.3.12345.1"
          ]
        }
      }
    ]
  }
}

Partial-failure response

202 (Accepted) — one instance stored, one failed. The failure appears in FailedSOPSequence with failure reason 272:

{
  "00081190": { "vr": "UR", "Value": ["https://dicom.example.com/studies/1.2.840.113619.2.55.3.604688119.868.1234567890.1"] },
  "00081198": {
    "vr": "SQ",
    "Value": [
      {
        "00081150": { "vr": "UI", "Value": ["1.2.840.10008.5.1.4.1.1.2"] },
        "00081155": { "vr": "UI", "Value": ["1.2.840.113619.2.55.3.12345.2"] },
        "00081197": { "vr": "US", "Value": [272] }
      }
    ]
  },
  "00081199": {
    "vr": "SQ",
    "Value": [
      {
        "00081150": { "vr": "UI", "Value": ["1.2.840.10008.5.1.4.1.1.2"] },
        "00081155": { "vr": "UI", "Value": ["1.2.840.113619.2.55.3.12345.1"] },
        "00081190": {
          "vr": "UR",
          "Value": [
            "https://dicom.example.com/studies/1.2.840.113619.2.55.3.604688119.868.1234567890.1/series/1.2.840.113619.2.55.3.604688119.868.1234567890.2/instances/1.2.840.113619.2.55.3.12345.1"
          ]
        }
      }
    ]
  }
}

Transfer syntax support

The following transfer syntaxes are recognized for ingest-time transcoding decisions. Transfer syntaxes not in this list are stored as-is (no transcoding is attempted). The same set governs retrieve-time transcoding.

Uncompressed:

UID Name
1.2.840.10008.1.2 Implicit VR Little Endian
1.2.840.10008.1.2.1 Explicit VR Little Endian
1.2.840.10008.1.2.2 Explicit VR Big Endian

Compressed:

UID Name
1.2.840.10008.1.2.5 RLE Lossless
1.2.840.10008.1.2.4.50 JPEG Baseline Process 1
1.2.840.10008.1.2.4.57 JPEG Lossless, Non-Hierarchical
1.2.840.10008.1.2.4.70 JPEG Lossless, Non-Hierarchical, First-Order Prediction
1.2.840.10008.1.2.4.80 JPEG-LS Lossless
1.2.840.10008.1.2.4.81 JPEG-LS Lossy
1.2.840.10008.1.2.4.90 JPEG 2000 Lossless Only
1.2.840.10008.1.2.4.91 JPEG 2000
1.2.840.10008.1.2.4.110 JPEG XL Lossless
1.2.840.10008.1.2.4.112 JPEG XL
1.2.840.10008.1.2.4.201 High-Throughput JPEG 2000 Lossless Only
1.2.840.10008.1.2.4.202 High-Throughput JPEG 2000 with RPCL Options Lossless Only
1.2.840.10008.1.2.4.203 High-Throughput JPEG 2000

Ingest transcoding rules

At store time, the first matching rule determines the target transfer syntax. If the instance is already in the target syntax (or no rule matches), it is stored unchanged:

Modality Condition Target transfer syntax
CR, CT, DX, MG, MR Always 1.2.840.10008.1.2.4.202 (HTJ2K RPCL Lossless Only)
NM, OT, PT, RF, SM, US Source transfer syntax is lossless 1.2.840.10008.1.2.4.202 (HTJ2K RPCL Lossless Only)

Transcoding can be disabled per request with the x-kastoria-disable-transcode: true header.

See also