Skip to main content

Upload and Deploy an AI Model

Overview

Authenticate each request with a WEDA bearer token that grants access to the target organization and devices. Obtain one through the standard SSO flow or as an M2M Client Credential.

The workflow has two parts:

  • Upload — create the model, register an edition, upload the binary, and wait for hash verification
  • Deploy — push the verified edition to target devices and confirm the result

Upload Flow

StepCallResult
1. Create modelPOST /api/v1/orgs/{orgId}/ai-models — body { modelName }201modelId. If the name already exists, 409 — list existing models and reuse the modelId
2. Register editionPOST /api/v1/orgs/{orgId}/ai-models/{modelId}/editions — body { edition, fileName, fileSize, fileHash }201uploadId, tusEndpoint
3. Create upload session (tus)POST /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/uploads — headers Tus-Resumable: 1.0.0, Upload-Length: {fileSize}, Upload-Metadata: uploadId {base64(uploadId)}201 + Location header containing the upload resource URL
4. Upload binary (tus PATCH)Send PATCH to the complete URL returned in the Location header — headers Tus-Resumable: 1.0.0, Upload-Offset: 0, Content-Type: application/offset+octet-stream, body = file bytes204; object stored, Upload-Offset equals fileSize
5. Check verification statusGET /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/uploads/{uploadId}/statusPending → Uploading → Verifying → Uploaded. WEDA Core re-hashes the file server-side; a mismatch sets VerifyFailed and deletes the object
note

Upload-Metadata in step 3 carries the registered uploadId returned from step 2, base64-encoded. For subsequent HEAD and PATCH requests, use the complete upload resource URL from the Location header without parsing or reconstructing it. Continue to use the registered uploadId when polling the upload status. The edition is identified throughout by the edition string you chose in step 2 (e.g. 1-0-3), not by a numeric ID.

Poll step 5 until the status reaches Uploaded before deploying.

Resuming or Abandoning an Upload

If the upload connection drops mid-transfer, query the current offset before resuming:

CallResult
Get current upload offsetHEAD to the same upload resource URL from the Location header — returns Upload-Offset and Upload-Length
Terminate the uploadDELETE to the same upload resource URL — cancels and removes the in-progress upload. Returns 204, or 404 if the upload resource no longer exists

Resume by sending the remaining bytes in a subsequent PATCH with Upload-Offset set to the value returned by HEAD.

Terminate instead when you want to start the transfer over. The uploadId stays valid — repeat step 3 with the same uploadId to create a fresh upload session. There is no need to register the edition again.

Upload Requirements

  • Complete the upload within 12 hours after registering the edition.
  • The maximum file size is 50 GiB.
  • Provide fileHash as a 64-character lowercase SHA-256 hexadecimal string.
  • Supply fileName, fileSize, and fileHash together. Omitting all three creates an empty edition in Pending status without starting an upload.

Deploy Flow

StepCallResult
6. DeployPOST /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}:deploy — body { targets[] }202{ modelDeploymentId, status: "IN_PROGRESS" }, each target at state: "SENT". The deployment is queued and delivered once the device is reachable
note

The deploy verb lives under /ai-models/ — there is no separate /models/ route.

The Deploy Body — Apply Pipeline

Each target device carries a tasks[] entry describing a four-phase action pipeline: preCmdvalidateCmdapplyCmdpostCmd. Every hook is an { action, params } pair drawn from a closed enum — WEDA Core never sends arbitrary shell commands to the device.

The tasks array is optional. If you omit it, WEDA still downloads the verified file to the device's Secured Volume, but it does not run additional lifecycle actions against a container or service. Omitting an individual hook (e.g. no preCmd key) has the same effect as setting it to NOOP for that stage — the stage is skipped without failing.

Common configuration — check disk space, verify the file's checksum, then atomically swap it in and restart the container:

{
"targets": [
{
"deviceIdList": ["000c29e353e9"],
"tasks": [
{
"preCmd": { "action": "CHECK_DISK_USAGE", "params": { "maxUsagePercent": "95" } },
"validateCmd": { "action": "CHECKSUM_VERIFY", "params": { "expectedChecksum": "...", "algorithm": "sha256" } },
"applyCmd": { "action": "ATOMIC_SWAP_AND_RESTART_CONTAINER", "params": { "containerName": "container1" } }
}
]
}
]
}

postCmd is omitted here — there is currently no tested postCmd action to recommend (see the actions table below). Omitting a hook has the same effect as setting it to NOOP for that stage — the stage is skipped without failing.

HookRecommended actionWhy
validateCmdCHECKSUM_VERIFYConfirms the downloaded file matches the expected hash before it's swapped in
applyCmdATOMIC_SWAP_AND_RESTART_CONTAINERSwaps the file into place and restarts the target container so it picks up the new version
important

When you use an action that operates on a container, such as ATOMIC_SWAP_AND_RESTART_CONTAINER, applyCmd.params.containerName must match a container that is already running on the device. The action does not create or mount the container. The container must already have the Secured Volume mounted; see Make Your Container Read the Model.

An action value outside the documented enum is rejected as a schema validation error (400).

All available actions and parameters

Each hook operates at a different point in the file's lifecycle — validateCmd runs against the working path (downloaded, not yet moved into place); applyCmd runs against the final path (after the atomic move). Using an action at the wrong stage fails because the path it expects doesn't exist yet.

ActionStageParams (✅ required)Behavior
CHECK_DISK_USAGEpreCmdmaxUsagePercent ✅ (0 < x ≤ 100)Fails if root filesystem usage exceeds the threshold
CHECKSUM_VERIFYvalidateCmdexpectedChecksum ✅ (hex), algorithm (sha256 default or sha512)Streaming hash comparison
ATOMIC_SWAP_AND_RESTART_CONTAINERapplyCmdcontainerNameConfirms the swap, then docker restart. A restart failure is non-fatal — the file is already deployed; a warning is logged and nothing is rolled back
NOOPpreCmdSkip the pre-command step; proceed directly to download
NOOPvalidateCmdSkip validation; trust the downloaded file as-is
NOOPapplyCmdSkip activation; the file remains in the staging directory and is never moved to its final path
NOOPpostCmdSkip the post-deployment health check; assume activation succeeded

Omitting a hook has the same effect as setting it to NOOP for that stage.

postCmd accepts only NOOP

NOOP is the only action defined for postCmd, which skips the post-deployment health check. Omitting the postCmd key has the same effect.

Check Deployment Result

Two read endpoints confirm a deployment — query by device, or by model edition. Both return a paged envelope.

OperationCallDescription
By deviceGET /api/v1/devices/{deviceId}/ai-models?maxResultCount=10&skipCount=0Per-device deployment records; each walks to the terminal state: DEPLOYED
By model editionGET /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/deployments?maxResultCount=10&skipCount=0One item per target device, with deviceId, state, edgeFilePath, deploymentStartTime, lastTransitionTime
{
"items": [
{
"modelDeploymentId": "d642d71e-0cbd-40db-a649-99cdb68def2d",
"modelName": "defect-detector",
"edition": "1-0-3",
"deviceId": "000c29e353e9",
"edgeFilePath": "/ai-models/defect-detector/1-0-3/model.bin",
"state": "DEPLOYED"
}
],
"skipCount": 0,
"maxResultCount": 10,
"totalCount": 1,
"totalPages": 1
}

What Happens on the Device

Once the deployment instruction reaches the device, the on-device agent (dmagent) takes over automatically:

  1. Signal receiveddmagent picks up the pending deployment
  2. Download — retrieves the model file into the device's secured volume
  3. Apply pipeline — runs the preCmd → validateCmd → applyCmd → postCmd sequence against the target container
Turn on CHECKSUM_VERIFY to verify the file on the device

WEDA Core re-hashes every upload server-side against the fileHash you registered — a mismatch sets VerifyFailed and deletes the object, so a corrupted upload never becomes deployable.

On the device, hash verification is opt-in: set validateCmd to CHECKSUM_VERIFY to have the device check the file before it is activated. With validateCmd omitted or set to NOOP, the deployment still reaches VALIDATED, but nothing is actually checked at that stage.

A deployment reports these edge-side stages on its way to DEPLOYED:

SENT → SERVERFILEPATH_OBTAINED → EDGERECEIVED → MODEL_STORAGE_CHECKED
→ CAPACITY_CHECKED → DOWNLOADED → VALIDATED → DEPLOYED

A REJECTED status carries a rejection reason identifying which stage failed.

Deployment Statuses

The deployment-level status summarizes the result across all target devices:

StatusMeaning
IN_PROGRESSAt least one target device is still processing the deployment.
COMPLETEDEvery target device reached DEPLOYED.
PARTIAL_FAILEDSome target devices reached DEPLOYED, while others were rejected.
FAILEDAll target devices were rejected.

Each target device reports its own state:

StateMeaning
SENTWEDA Core accepted and dispatched the deployment request.
SERVERFILEPATH_OBTAINEDThe device resolved the source file location.
EDGERECEIVEDThe device received the deployment instruction.
MODEL_STORAGE_CHECKEDThe device verified that model storage is available.
CAPACITY_CHECKEDThe device confirmed that sufficient storage capacity is available.
DOWNLOADEDThe device downloaded the model file.
VALIDATEDThe downloaded file passed the configured validation.
DEPLOYEDThe model file was placed in its active location successfully.
REJECTEDThe device rejected the deployment. Inspect the rejection reason for details.
DELETEDThe deployed file was removed from the device.

Device Offline Behavior

Issuing a deployment never checks whether the target device is online — a request to an offline device is accepted the same as any other. The deployment is queued and will apply automatically when the device reconnects. While the device is unreachable, its state remains SENT.

Deployments do not time out while a device is offline — they remain pending indefinitely until the device reconnects.

Deploying the Same Model More Than Once

A deployment is identified by its deployment path — the combination of model name, edition, and file name. What happens when you deploy again depends on how the new deployment compares with what is already on the device:

New deployment vs. existingResult
Any of model name, edition, or file name differsBoth deployments coexist on the device
Deployment path and file hash both matchThe request is rejected
Deployment path matches but the file hash differsThe existing file is replaced

A rejected deploy fails at the API call, not later in the device state: the request returns 409 with error code AiModelMgmt:ConflictingModelDeployment, and the response's extension.devices lists the devices that already hold that file.

Recreating a model with the same name and edition but a different file name therefore produces a second, coexisting deployment. Recreating it with the same file name but different content replaces what is already on the device.

Managing Models and Editions

Beyond the upload and deploy flow, these operations let you inspect and maintain models and their editions.

OperationAPIDescription
List Editions of a ModelGET /api/v1/orgs/{orgId}/ai-models/{modelId}/editionsReturns a paginated list of editions for the specified model
Get Model Edition DetailGET /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}Returns the full metadata for a single model edition
Update Edition MetadataPATCH /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}Updates the editable metadata of an existing edition
Update Model Basic InfoPATCH /api/v1/orgs/{orgId}/ai-models/{modelId}Updates the basic, model-level metadata. Editions are unaffected

Constraints

  • After an edition's file passes upload verification, its file content cannot be replaced. Descriptive metadata can still be updated. Re-registering an edition that is still Pending reuses it, so an interrupted upload can be retried; re-registering an edition that already has a verified file returns 409 EditionAlreadyExists.
  • An edition with VerifyFailed status cannot be deployed
  • You can deploy only to devices that belong to an organization you are authorized to manage. The deployment ACL fields allowedContainers and allowedSubnets separately control access to the deployed file on the device.
  • A deployment reaches DEPLOYED once the device is reachable and applies it; while offline, it remains queued indefinitely — see Device Offline Behavior

Teardown

StepCallResult
Remove from deviceDELETE /api/v1/devices/{deviceId}/ai-models/{modelId}/editions/{edition}202 — the removal is queued and applied once the device is reachable
Remove from all deployed devicesDELETE /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/deployments202 — requests removal from every device that received the edition
Delete a Single EditionDELETE /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}Permanently deletes the specified model edition, leaving the model and its other editions in place
Delete the modelDELETE /api/v1/orgs/{orgId}/ai-models/{modelId}Hard delete — permanently removes the model, all its editions, uploads, and stored files from WEDA Core

Removing an edition from devices and deleting the cloud model are independent operations — neither requires the other, and there is no ordering constraint between them:

  • You do not need to remove an edition from its devices before deleting the model from WEDA Core
  • A device's online/offline status has no effect on whether the cloud model can be deleted
  • Deleting the cloud model does not touch files already deployed to a device's Secured Volume — those remain in place until separately removed via Remove from device
  • Because deletion is a hard delete, a (modelName, edition) pair can be reused immediately after the original model is deleted — the name is not reserved by a soft-deleted record

Last updated on Aug-1, 2026 | Version 1.1.1