Predict.aiDocs
Models

BYOM

Bring your own model — upload a pre-trained artifact, validate it, and register it as a model you can deploy.

Already trained a model elsewhere? BYOM (bring your own model) puts it in your catalog in three calls: upload the file, validate it (the platform detects the framework, infers the input/output signature, and runs a live forward pass), then register it as a kind: "byom" model.

Accepted formats: PyTorch (.pt), TensorFlow/Keras (.h5, SavedModel), ONNX (.onnx), and scikit-learn / XGBoost pickles (.pkl).

Upload size is capped by your plan (the byom_max_mb limit — for example Starter allows files up to 500 MB, Team up to 2 GB, and Enterprise has no cap; the free tier doesn't include BYOM). The cap is resolved from your plan automatically on every call. Uploads also charge credits per MB — see Billing for tiers and rates.

Step 1 — Upload

Send the artifact as a multipart file field. The upload is charged per MB before storage (and refunded automatically if storage fails):

curl -X POST "$API_BASE/v1/models/byom/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -F "file=@./sales_forecaster.onnx"
{
  "data": {
    "model_id": "1f4c3a9e6b8d4e219c7a5b3f8d2e6a41",
    "model_uri": "s3://celmind-byom/ORG_ID/1f4c3a9e…/v1/model.onnx",
    "local_staging_path": "/tmp/byom_1f4c3a9e….onnx",
    "size_bytes": 48211284,
    "ext": ".onnx",

  }
}

Keep the model_id — the next two calls take it.

Request

FieldMeaning
file requiredThe model artifact, as a multipart form field. One file per upload.

Errors

StatusWhyExample message
400No file in the request"multipart 'file' field required"
400Empty file"file is empty"
402Not enough credits for the per-MB upload chargeerror.code insufficient_credits, error.details.needed 46.0
403Your plan doesn't include BYOMerror.code plan_limit
413File exceeds your plan's size caperror.code plan_limit, error.details.cap_mb 500

Step 2 — Validate

Validation auto-detects the framework, infers the model's signature, and runs one forward pass with random input of the inferred shape. It's a paid operation (byom.validate):

curl -X POST "$API_BASE/v1/models/byom/validate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "model_id": "1f4c3a9e6b8d4e219c7a5b3f8d2e6a41" }'
{
  "data": {
    "model_id": "1f4c3a9e6b8d4e219c7a5b3f8d2e6a41",
    "detection": { "framework": "onnx", "confidence": 0.98, "notes": "ONNX graph header" },
    "signature": {
      "input_signature":  [ { "name": "input",  "shape": [-1, 20, 3], "dtype": "float32" } ],
      "output_signature": [ { "name": "output", "shape": [-1, 14, 1], "dtype": "float32" } ]
    },
    "validation": {
      "ok": true,
      "framework": "onnx",
      "file_size_bytes": 48211284,
      "static_warnings": [],
      "static_errors": [],
      "dynamic_passed": true,
      "forward_latency_ms": 11.4,
      "output_shape": [1, 14, 1],
      "notes": ""
    }
  }
}

Request body

FieldMeaning
model_id requiredThe ID from upload.
framework optionalSkip auto-detection: onnx, pytorch, tensorflow, sklearn, xgboost.
input_shape_hint optionalAn input shape like [1, 20, 3] — helps when signature inference is ambiguous.

Response fields

FieldMeaning
detectionThe detected framework with a confidence score and what gave it away.
signatureThe inferred input_signature / output_signature — name, shape, dtype per tensor. You pass these back at register.
validationThe verdict: ok, static_warnings / static_errors, whether the live forward pass ran (dynamic_passed), and its latency.

A model that fails validation still returns 200 — check validation.ok and read static_errors:

"static_errors": ["File size 812.4 MB exceeds your plan's cap of 500 MB"]

Pickle files get a standing warning: they execute code at load time, so consider re-exporting to ONNX.

Errors

StatusWhyExample message
400No model_id in the body"model_id required"
404Upload expired or wrong id"No staged file found for model_id 1f4c…"
402Not enough creditserror.code insufficient_credits, error.details.operation "byom.validate"

Step 3 — Register

Pass the signature and validation objects from step 2 back in, plus a name. This creates the catalog entry:

curl -X POST "$API_BASE/v1/models/byom/register" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "1f4c3a9e6b8d4e219c7a5b3f8d2e6a41",
    "model_uri": "s3://celmind-byom/ORG_ID/1f4c3a9e…/v1/model.onnx",
    "framework": "onnx",
    "name": "Sales forecaster (imported)",
    "description": "Trained offline on 3 years of daily sales",
    "visibility": "private",
    "signature": { "input_signature": […], "output_signature": […] },
    "validation": { "ok": true, … },
    "segment_id": "SEGMENT_ID"
  }'
{
  "data": {
    "blueprint_id": "b7d2e911-…",
    "model_id": "5a80c4f3-…",
    "training_id": "e2c619ab-…",

  }
}

Request body

FieldMeaning
model_id requiredThe ID from upload.
model_uri requiredThe storage URI from the upload response, echoed back.
framework requiredThe framework from the validation response.
name requiredDisplay name for the catalog entry.
signature requiredThe signature object from validate, passed back unchanged.
validation requiredThe validation object from validate, passed back unchanged. ok must be true.
segment_id optionalBind the model to a segment: also creates a pipeline and a ready-to-promote training record (see below).
description optionalFree-text description.
visibility optionalprivate (default) or public.
license optionalDefaults to proprietary.
preprocessing optionalPreprocessing applied before inference.

Response fields

FieldMeaning
blueprint_idThe new model's catalog ID (response fields use the internal name, like the route paths).
model_idOnly when segment_id was passed: the ID of the pipeline created to bind the model to that segment.
training_idOnly when segment_id was passed: a ready-to-promote training record — go straight to deploy with one POST /v1/deployments call.

Omit segment_id and you get just the catalog entry.

Compatibility with your segment

When you pass a segment_id, the platform checks the model's signature against the segment's layout before saving anything: the number of input features must match the segment's features (base + engineered), and the output must map onto the segment's labels. Mismatches return a 422 with the concrete issue — never a broken deployment later:

{
  "error": {
    "code": "byom_incompatible_segment",
    "message": "The model's signature doesn't match the segment's feature/label layout.",
    "details": {
      "issues": ["Model expects 5 input features per step but the segment provides 3 (revenue, units, price)."],
      "expected": { "n_features": 3, "features": ["revenue", "units", "price"], "n_labels": 1, "labels": ["revenue"] }
    }
  }
}

The same check runs when you later create a pipeline from a registered BYOM model (POST /v1/pipelines) and again as a backstop at promotion time — so a segment whose features changed since registration is caught before it can break serving.

Errors

StatusWhyExample message
400Required field missing"Missing required fields: signature, validation"
403Plan quota for uploaded models reached"BYOM model limit reached. Your plan allows 3 uploaded models per workspace."
404Segment not found in this workspace"Segment SEGMENT_ID not found in this workspace"
422Signature doesn't fit the segmenterror.code byom_incompatible_segment
422Artifact can't be converted for servingerror.code byom_staging_failed

BYOM models don't count against the regular per-workspace model quota — they have their own byom_models quota, checked here at register time. See Billing.

Download your model

Your model is never locked in. Fetch a time-limited download link for the exact file you uploaded:

curl "$API_BASE/v1/models/byom/BLUEPRINT_ID/download" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"
{
  "data": {
    "download_url": "https://celmind-byom.s3.amazonaws.com/…&X-Amz-Expires=3600…",
    "filename": "9f2c41d8-7b3a-4e1f-8c2d-5a6b7c8d9e0f.onnx",
    "framework": "onnx",
    "expires_in_seconds": 3600
  }
}

The URL is valid for one hour; request a fresh one any time. The file saves under the model's ID (the download link carries a Content-Disposition header, so the name is applied automatically).

Errors

StatusWhyExample message
403Not your model (and not public)"You don't have access to this model"
404Unknown id, or not a BYOM model"BYOM model BLUEPRINT_ID not found"

On this page