CreateEnrichmentJob for Scenario Discovery
Prerequisites
A Scenario Discovery workspace and dataset containing video data
CreateEnrichmentJob operates on an existing workspace + dataset. Before
you can call it:
-
The workspace must exist and be in ACTIVE state (not being deleted).
-
The dataset must exist inside that workspace and must contain the MP4 video time-series data to be analyzed. Use
CreateBulkImportJobto ingest video data into a dataset if you haven't already. -
If two requests share the same job type, workspace, property, and dataset but specify different time ranges, the system accepts both requests.
Your calling identity needs permission to invoke the enrichment-job APIs, read the target workspace/dataset/time-series resources, and (when the workspace uses a customer managed KMS key) decrypt with that key.
Minimal caller permission policy:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "InvokeEnrichmentJob", "Effect": "Allow", "Action": [ "iotsitewise:CreateEnrichmentJob", "iotsitewise:DescribeEnrichmentJob", "iotsitewise:CancelEnrichmentJob", "iotsitewise:ListEnrichmentJobs" ], "Resource": "*" }, { "Sid": "ReadWorkspaceAndDataset", "Effect": "Allow", "Action": [ "iotsitewise:DescribeWorkspace", "iotsitewise:DescribeDataset", "iotsitewise:ListDatasetDataSegments", "iotsitewise:ListTimeSeries", "iotsitewise:DescribeTimeSeries" ], "Resource": "*" }, { "Sid": "DecryptWorkspaceCMK", "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:DescribeKey" ], "Resource": "arn:aws:kms:us-east-1:123456789012:key/00000000-0000-0000-0000-000000000000", "Condition": { "StringEquals": { "kms:ViaService": "iotsitewise.us-east-1.amazonaws.com" } } } ] }
Notes:
-
Omit or narrow
DecryptWorkspaceCMKwhen the workspace uses the default Amazon managed key. Include it (with the correct key ARN) when the workspace was created with a customer managed KMS key. -
The service itself performs the video processing — you do not pass a service role (there is no
jobRoleArn-style parameter). You only grant the caller enough permission to submit and track the job. -
AccessDeniedExceptionfrom the API almost always indicates missing Amazon IoT SiteWise or KMS permissions on the caller identity.
If your caller is an application role, pair the policy with a trust policy for the workload type that runs the code:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ec2.amazonaws.com", "ecs-tasks.amazonaws.com", "lambda.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
Trim the Service list to only the workload type that actually runs your code.
Aliases
Enrichment is scoped to a single video time series within the dataset. You identify that
time series either by its system-assigned timeSeriesId or by its
propertyAlias. Aliases are strongly preferred because they're readable, stable,
and consistent with the alias conventions used during bulk import.
For a vehicle-mounted camera, the alias follows the same structure used for MP4 imports:
/car_120/front_left_camera/
Specify exactly one of propertyAlias or timeSeriesId in the
request — never both. The API returns ValidationException if both are
supplied.
Request shape
Required top-level parameters
| Parameter | Type | Notes |
|---|---|---|
workspaceName |
string | Name of the Scenario Discovery workspace (1–64 chars,
^[a-zA-Z0-9_-]+$). Sent as a URI path parameter, not in the JSON
body. |
jobConfiguration |
structure | Configuration union. Currently must contain exactly one member:
eventDetection. |
Optional top-level parameters
| Parameter | Type | Notes |
|---|---|---|
clientToken |
string | 36–64 chars, no whitespace. Idempotency token — resubmitting the same request with the same token returns the original job without creating a duplicate. Use a UUID. |
EnrichmentJobConfiguration (union — exactly one member)
Currently the only supported member is eventDetection.
EventDetection fields:
| Field | Required | Notes |
|---|---|---|
datasetId |
yes | ID of the Scenario Discovery dataset containing the video time series |
timeSeriesId |
one of timeSeriesId/alias | System-generated identifier for the video time series. 36–73 chars. |
propertyAlias |
one of timeSeriesId/alias | Human-readable alias for the video time series (max 2048 chars). Preferred. |
trimSettings |
yes | { startTime, endTime } — bounds the time window to process. Both
bounds must lie within the dataset's actual time bounds. |
EnrichmentTrimSettings
Both startTime and endTime are TimeInNanos structures:
{ "timeInSeconds": <Unix epoch seconds>, "offsetInNanos": <optional 0..999999999> }
endTime must be strictly greater than startTime, and both
must fall within the dataset's data range.
Note
Only data segments FULLY encapsulated within this time range are enriched. Partial enrichment of data segments is not supported.
Python helper to compute the seconds/nanos split:
import datetime def as_time_in_nanos(dt: datetime.datetime) -> dict: ts_ns = int(dt.timestamp() * 1_000_000_000) return { "timeInSeconds": ts_ns // 1_000_000_000, "offsetInNanos": ts_ns % 1_000_000_000 }
Response
{ "jobId": "string", "status": "PENDING | RUNNING | COMPLETED | FAILED | TIMED_OUT | CANCELLED", "createdAt": "2026-07-14T17:00:00Z" }
HTTP status on success: 200 OK. (Unlike CreateBulkImportJob which returns
202, CreateEnrichmentJob returns 200.)
Errors
| Error | Meaning |
|---|---|
ValidationException |
Invalid parameters (for example, both timeSeriesId and propertyAlias specified, endTime <= startTime) |
AccessDeniedException |
Missing Amazon IoT SiteWise or KMS permissions on the caller |
ConflictException |
A duplicate job (same workspace/dataset/property/type) is already running |
ResourceNotFoundException |
Workspace, dataset, or time series does not exist |
ThrottlingException |
Request rate exceeded |
LimitExceededException |
Too many concurrent jobs |
InternalServerException |
Service-side failure |
Example request payload
Save this as enrichment-job-request.json. The workspaceName is
passed on the URL path (or through a CLI flag), not in the JSON body.
{ "jobConfiguration": { "eventDetection": { "datasetId": "9005f70f-ebb6-4380-b0f8-6ed83ddbea6a", "propertyAlias": "/camera/front", "trimSettings": { "startTime": { "timeInSeconds": 1778275007, "offsetInNanos": 0 }, "endTime": { "timeInSeconds": 1778275307, "offsetInNanos": 0 } } } }, "clientToken": "c9c1d2b8-2f4b-4d6a-9b83-8b8a9b9d9a0a" }
Notes:
-
1778275007 and 1778275307 represent a 5-minute analysis window.
-
clientTokenis optional but recommended. If your caller retries, use the same token to avoid creating a duplicate job. -
Only data segments fully contained within the
trimSettingstime range are enriched. Segments overlapping the start or end boundary but not fully within it are ignored.
Amazon CLI
Command (using an input file):
aws iotsitewise create-enrichment-job \ --region us-east-1 \ --workspace-name scenario_discovery_car120 \ --cli-input-json file://enrichment-job-request.json
Equivalent inline form:
aws iotsitewise create-enrichment-job \ --region us-east-1 \ --workspace-name ws-1778278606 \ --job-configuration '{ "eventDetection": { "datasetId": "9005f70f-ebb6-4380-b0f8-6ed83ddbea6a", "propertyAlias": "/camera/front", "trimSettings": { "startTime": { "timeInSeconds": 1778275007 }, "endTime": { "timeInSeconds": 1778275307 } } } }'
CLI-only flags:
-
--region <name>(orAWS_REGIONenv var) — required -
--profile <name>— selects a named profile from~/.aws/config -
--cli-input-json file://...— read the request body from a JSON file -
--generate-cli-skeleton— print a blank request template
Sample output:
{ "jobId": "9a8b7c6d-5e4f-3a2b-1c0d-e1f2a3b4c5d6", "status": "PENDING", "createdAt": "2026-07-14T17:00:00Z" }
boto3 (Python)
import uuid import boto3 client = boto3.client("iotsitewise", region_name="us-east-1") response = client.create_enrichment_job( workspaceName="ws-1778278606", jobConfiguration={ "eventDetection": { "datasetId": "9005f70f-ebb6-4380-b0f8-6ed83ddbea6a", "propertyAlias": "/camera/front", "trimSettings": { "startTime": {"timeInSeconds": 1778275007, "offsetInNanos": 0}, "endTime": {"timeInSeconds": 1778275307, "offsetInNanos": 0}, }, }, }, clientToken=str(uuid.uuid4()), ) print(response["jobId"], response["status"], response["createdAt"])
boto3-specific notes:
-
region_name— required, passed toboto3.client()or set throughAWS_REGION/AWS_DEFAULT_REGION -
Credentials resolve through the standard boto3 chain (env vars,
~/.aws/credentials, instance/task role, SSO) -
All request parameters use camelCase names matching the API model.
workspaceNameis passed as a kwarg; boto3 places it on the URL path for you. -
Wrap calls in
try / except botocore.exceptions.ClientErrorto handle:ValidationException,AccessDeniedException,ConflictException,ResourceNotFoundException,ThrottlingException,LimitExceededException,InternalServerException
curl (raw HTTPS)
CreateEnrichmentJob is POST
/workspaces/{workspaceName}/enrichment-jobs on the Amazon IoT SiteWise data plane endpoint. Every
request must be signed with Amazon Signature Version 4 (SigV4).
Endpoint
https://data.iotsitewise.<region>.amazonaws.com/workspaces/<workspaceName>/enrichment-jobs
HTTP required elements
| Element | Value |
|---|---|
| Method | POST |
| Path | /workspaces/<workspaceName>/enrichment-jobs |
| Host header | data.iotsitewise.<region>.amazonaws.com |
| Content-Type header | application/json |
| X-Amz-Date header | ISO 8601 basic format (for example, 20260714T170000Z) |
| X-Amz-Security-Token | Required only with temporary credentials (STS) |
| Authorization header | SigV4 signature (service = iotsitewise) |
| Body | The JSON request payload |
Recommended: awscurl
awscurl \ --service iotsitewise \ --region us-east-1 \ -X POST \ -H "Content-Type: application/json" \ -d @enrichment-job-request.json \ https://data.iotsitewise.us-east-1.amazonaws.com/workspaces/scenario_discovery_car120/enrichment-jobs
Plain curl — pre-signed request skeleton
curl -v -X POST \ "https://data.iotsitewise.us-east-1.amazonaws.com/workspaces/scenario_discovery_car120/enrichment-jobs" \ -H "Host: data.iotsitewise.us-east-1.amazonaws.com" \ -H "Content-Type: application/json" \ -H "X-Amz-Date: 20260714T170000Z" \ -H "X-Amz-Security-Token: <SESSION_TOKEN_IF_TEMP_CREDS>" \ -H "Authorization: AWS4-HMAC-SHA256 \ Credential=<ACCESS_KEY_ID>/20260714/us-east-1/iotsitewise/aws4_request, \ SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, \ Signature=<COMPUTED_HEX_SIGNATURE>" \ --data-binary @enrichment-job-request.json
See the Amazon documentation on Signing Amazon API requests for the full SigV4 derivation.
Sample HTTP response:
HTTP/1.1 200 OK Content-Type: application/json { "jobId": "9a8b7c6d-5e4f-3a2b-1c0d-e1f2a3b4c5d6", "status": "PENDING", "createdAt": "2026-07-14T17:00:00Z" }
Verifying the job
aws iotsitewise describe-enrichment-job \ --region us-east-1 \ --workspace-name scenario_discovery_car120 \ --job-id 9a8b7c6d-5e4f-3a2b-1c0d-e1f2a3b4c5d6
The status progresses: PENDING → RUNNING → one of
COMPLETED, FAILED, TIMED_OUT, or
CANCELLED.
-
COMPLETED— embeddings are available and the video can be searched through Scenario Discovery's semantic search. -
FAILED— inspect thefailureMessagefield in theDescribeEnrichmentJobresponse for details.
Cancelling a running job
aws iotsitewise cancel-enrichment-job \ --region us-east-1 \ --workspace-name scenario_discovery_car120 \ --job-id 9a8b7c6d-5e4f-3a2b-1c0d-e1f2a3b4c5d6
CancelEnrichmentJob is idempotent — calling it more than once for the
same jobId returns the current status without error, as long as the job is not
already in a non-CANCELLED terminal state (COMPLETED, FAILED,
TIMED_OUT), in which case it returns ConflictException.
Cancelling a RUNNING enrichment job might fail with an exception if data ingestion into
the storage service has already begun.