Skip to main content
The REST API uses a shared job lifecycle: upload data, submit work, poll its status, and read the result. A fit ends with a reusable context instead of a separate result.
In Python, use the Python SDK. It handles compression, uploads, polling, retries, and large results automatically.

Configure

Use your deployment origin as the base URL:
Send your API key as a bearer token:
Every /v1 endpoint requires a key except GET /v1/model-limits. See Get your API key for issuing and rotating keys. Requests are limited to 60 per minute per user, shared across that user’s keys. A rate-limited response includes Retry-After. See Limits and quotas for every ceiling.

Choose a workflow

Each workflow starts by uploading its data through POST /v1/uploads.

Endpoints

Wire fields use camelCase and IDs are opaque strings. Submission endpoints return 200 with a job whose status is queued; subsequent progress is reported through the job status.

Upload data

Serialize the payload as JSON, gzip it, and hash the exact gzipped bytes you will upload:
Request an upload plan. contentHash accepts sha256:<hex> or bare hex. bytes is the exact gzipped length.
Upload the same gzipped bytes. The signed URL does not use your API key and expires after 1 hour.
rows and columns are optional, but must be sent together. They let Hollerith begin warming the appropriate worker while the upload completes. You can also send the same values directly to POST /v1/warm before the payload is ready.
Payloads over 64 MiB return kind: "multipart" with uploadId, partSize, partUrls, and completeUrl.Upload each part in order, retain its ETag, then POST this manifest to completeUrl with Content-Type: application/xml:
Part numbers start at 1 and ETags retain their quotes. Payloads above the upload limit return payload_too_large (413).

Predict rows

Submit the upload reference and row counts:
See Limits and quotas for row, column, cell, and class limits.

Poll and read results

Poll the job status endpoint until status is succeeded or failed:
A failed job includes its typed error in error. Request /result only after the job succeeds:
predictions follows the order of the uploaded rows. classes defines the probability column order, and quantiles follows quantileLevels. Results remain available for 1 hour. For a result over 512 KiB, the response contains resultUrl and resultContentHash instead of inline arrays. Download the signed URL within 5 minutes, gunzip its contents, and verify its SHA-256 hash.

Reuse a fitted context

POST /v1/fits accepts the prediction fields without outputRowCount. It also accepts forceRefit; set it to true to skip reuse of an identical active fit. The response returns a job, context, and reused flag:
Poll GET /v1/fits/{contextId} until the context is ready. Its status is one of creating, ready, failed, expired, or deleted. To predict with the context, upload only the rows to score. Set kind to "contextPrediction" in the uploaded payload, then submit: Contexts expire after 30 days of inactivity and after 90 days at the latest. Successful predictions extend the inactivity deadline.

Evaluate a fit

POST /v1/evaluations accepts the fit fields with rowCount instead of outputRowCount. Poll the shared job status endpoint, then read the evaluation result:
method is selected by row count. folds is omitted for a holdout evaluation. See Evaluating accuracy for interpreting the result.

Forecast a time series

POST /v1/forecasts accepts objectKey, contentHash, covariateColumns, contextRowCount, outputRowCount, and an optional idempotencyKey. Set kind to "forecast" in the uploaded payload. Poll the shared job status endpoint and read the result from GET /v1/predictions/{jobId}/result. Each prediction contains item_id, timestamp, mean, and one field per quantile level. GET /v1/forecasts/{id} returns 404. Poll forecasts through the shared prediction-job route.
  • outputRowCount equals the number of future rows, or the horizon multiplied by the number of distinct item_id values.
  • covariateColumns lists the covariate keys in the payload.
Forecasting is Beta and does not use a fitted context.

Payload shapes

Uploaded data is gzipped JSON. Required keys depend on the job: trainingFeatures, rows, context, and future are arrays of objects keyed by column name. trainingTarget is a flat array aligned with trainingFeatures. A forecast payload includes all four forecast keys and sets exactly one of future and predictionLength.

Use idempotency keys

Every job submission accepts an optional idempotencyKey, such as predict:churn-v3:batch-0912. Reusing a key with the same payload returns the original job. Reusing it with a different payload returns idempotency_conflict (409). Send an idempotency key with every submission. Without one, retrying after a network timeout can create a second billed job.

Handle errors

Typed errors include code, category, problem, cause, fix, docUrl, retryable, and requestId. Branch on code. See Errors for every code, HTTP status, and retry rule. Invalid JSON returns 400 {"error":"invalid_json"}. A request that matches no accepted shape returns 400 {"error":"invalid_request"}.

What the SDK handles

quantiles, predictionLength, and future belong in the uploaded payload rather than the submission body. REST integrations can use all three. The Python SDK builds, compresses, hashes, and uploads payloads. It also handles multipart uploads, status polling, cold-worker retries, and large-result downloads.

Next