Worked HTTP workflows
Role: Client integrator implementing granular HTTP operations. Prerequisites: An authenticated CLI profile, jq, and access to the selected model; curl and a scoped personal token for the raw HTTP examples. Files: Saved model discovery, request body, operation key, receipt and optional private HTTP headers.
For ordinary CLI executions and scripts, use the analysis-directory workflow and noninteractive JSON recipe. This page documents integration contracts and the raw API escape hatch. The HTTP reference defines each endpoint’s complete request, response, status and permission contract. These examples show how to combine those endpoints. Use your deployed service’s /api/v1/openapi.json when its version differs from this documentation.
Call an endpoint through the CLI
Section titled “Call an endpoint through the CLI”enumeray api handles profile credentials and structured errors while exposing methods and paths directly. Its --file is a JSON request body; it does not upload the contents of files mentioned inside that JSON. Paths must begin with /api/v1/ and include any query string:
enumeray --json api GET /api/v1/meenumeray --json api GET /api/v1/modelsenumeray --json api GET '/api/v1/runs?model_id=example&status=succeeded&limit=100'Analysis directories validate scientific inputs, retain reviewed publication/disclosure, bind the API/account and manage upload/submission recovery. Independent artifact commands manage reusable transfers. The raw api escape hatch does not add those workflow checks; integrations must preserve their own exact request, identity and retry evidence.
Discover, save and submit one JSON operation
Section titled “Discover, save and submit one JSON operation”Start in a new private directory. This example assumes the scalar fixture’s value input. Review the selected model’s real contract and disclosure before submitting.
umask 077mkdir http-runcd http-runMODEL_ID=exampleenumeray --json api GET "/api/v1/models/$MODEL_ID" > model.jsonjq '.current_publication | {definition, execution_location, disclosure}' model.jsonPUBLICATION_ID=$(jq -er '.current_publication_id' model.json)jq -n --arg model "$MODEL_ID" --arg publication "$PUBLICATION_ID" \ '{model_id: $model, expected_publication_id: $publication, inputs: {value: 2}}' \ > request.jsonpython3 -c 'import uuid; print(uuid.uuid4())' > operation-key.txtrequest.json is a complete HTTP body:
{ "model_id": "example", "expected_publication_id": "release-one", "inputs": {"value": 2}}The expected publication prevents silently running a newer contract than you reviewed. The operation key identifies the intended run, independently of the HTTP request ID. Keep both files unchanged after the first submission:
OPERATION_KEY=$(cat operation-key.txt)enumeray --json api POST /api/v1/runs --file request.json \ --idempotency-key "$OPERATION_KEY" > receipt.jsonRUN_ID=$(jq -er '.run_id' receipt.json)enumeray --json api GET "/api/v1/runs/$RUN_ID" > run.jsonjq '{state, phase, cancellation, result}' run.jsonRepeat the same POST with the saved key and body after a timeout or lost reply. Both first acceptance and exact replay return HTTP 201 with the original receipt and a Location pointing to the run. The receipt’s state remains queued; GET the run for current state. A changed request with the same key is a conflict. Unlike analysis-directory submission, api does not verify that saved files belong to the same account, so your integration must preserve that identity too.
Supply authentication to curl
Section titled “Supply authentication to curl”Create a personal token while signed in with your regular account. The example scopes permit discovery, submission, reading, cancellation and identity verification:
enumeray auth token-create http-client \ --scopes me:read,models:read,runs:create,runs:read,runs:cancel \ --expires-in-seconds 86400 --output token.jsonumask 077jq -er '"Authorization: Bearer " + .token' token.json > auth-header.txtAPI_URL=https://enumeray.example.orgcurl --fail-with-body --silent --show-error --header @auth-header.txt \ "$API_URL/api/v1/me"Use your real API origin. The header file keeps the bearer value out of process arguments. It remains a credential: keep it private along with token.json. Token scopes do not replace account/model access. Refresh this header file after issuing a replacement token; personal tokens do not use the browser refresh flow.
To submit the saved JSON request with curl, first persist a header file containing the same operation key:
{ cat auth-header.txt; printf 'Idempotency-Key: %s\n' "$(cat operation-key.txt)"; } \ > submission-headers.txtcurl --fail-with-body --silent --show-error \ --header @submission-headers.txt --header 'Content-Type: application/json' \ --data-binary @request.json --dump-header response-headers.txt \ "$API_URL/api/v1/runs" > curl-receipt.jsonInspect the HTTP status and JSON body. --fail-with-body returns nonzero on HTTP errors while retaining the error response. Do not automatically retry validation, authorization or generation conflicts. Keep x-request-id from response headers for diagnosis; it changes on every request and cannot replace the operation key.
Submit small files in one multipart request
Section titled “Submit small files in one multipart request”For clients that already implement HTTP, the run endpoint also accepts bounded multipart/form-data. The normal CLI file workflow binds sources with analysis init --file SLOT=PATH and manages verified uploads automatically; see file inputs. Multipart is convenient for small attachments and requires configured versioned storage. It accepts at most eight attachments and is also subject to the service’s general request-body limit.
For the file starter, use new operation-specific files in the same private directory as auth-header.txt above, and discover the model’s current publication. Save a JSON part that binds the scientific dataset slot to the multipart part named data:
MODEL_ID=csv-exampleenumeray --json model get "$MODEL_ID" > file-model.jsonPUBLICATION_ID=$(jq -er '.current_publication_id' file-model.json)jq -n --arg model "$MODEL_ID" --arg publication "$PUBLICATION_ID" \ '{model_id: $model, expected_publication_id: $publication, inputs: {dataset: {attachment: "data"}}}' > multipart-request.jsoncat > dataset.csv <<'CSV'index,value0,21,3CSVpython3 -c 'import uuid; print(uuid.uuid4())' > multipart-key.txt{ cat auth-header.txt; printf 'Idempotency-Key: %s\n' "$(cat multipart-key.txt)"; } \ > multipart-headers.txtcurl --fail-with-body --silent --show-error --header @multipart-headers.txt \ --form 'request=@multipart-request.json;type=application/json' \ --form 'data=@dataset.csv;type=text/csv' \ "$API_URL/api/v1/runs" > multipart-receipt.jsonRUN_ID=$(jq -er '.run_id' multipart-receipt.json)Keep the JSON part, part names, media type, file bytes and key unchanged on exact retry. The server verifies and publishes the attachment as an artifact at acceptance; run inspection retains requested attachment inputs and effective artifact references. attachment belongs to this multipart envelope. Ordinary JSON submission uses artifact_id for an already-completed upload.
Let curl set the multipart boundary. The request part must have application/json, and a file part’s media type must match the scientific declaration. Do not send an author publication or a wrapper protocol request as a run submission.
Stream logs and reconnect
Section titled “Stream logs and reconnect”Use the RUN_ID from the receipt and the private auth-header.txt above:
curl --no-buffer --fail-with-body --silent --show-error \ --header @auth-header.txt --header 'Accept: text/event-stream' \ --dump-header stream-headers.txt \ "$API_URL/api/v1/runs/$RUN_ID/logs/stream"A log event has an opaque id, event: log and a JSON data payload containing a log entry. A client must durably retain the ID only after processing the entry. Reconnect after that ID using either Last-Event-ID or ?cursor=..., never both. For example, to follow from the end of a drained retained page:
enumeray --json run logs "$RUN_ID" > logs.json# Follow next_cursor pages first if present; use the final page here.RESUME_CURSOR=$(jq -er '.resume_cursor' logs.json)ENCODED_CURSOR=$(jq -rn --arg value "$RESUME_CURSOR" '$value|@uri')curl --no-buffer --fail-with-body --silent --show-error \ --header @auth-header.txt --dump-header stream-headers.txt \ "$API_URL/api/v1/runs/$RUN_ID/logs/stream?cursor=$ENCODED_CURSOR"An HTTP 410 response means the cursor precedes retained history. Use X-History-Recovery-Cursor from the response headers and explicitly report the omitted prefix. During an open stream, handle retention_gap similarly; auth_revoked, source_unavailable and shutdown are control events that close the response. Keepalive comments are not log entries. Connection closure and silence do not establish scientific completion: independently GET the run and drain the retained final logs.
Send management JSON
Section titled “Send management JSON”Execution-context manifests still send their spec to the matching HTTP endpoint. Editable author publication.json uses a different local format. Prefer model release init and resume for durable candidate registration from that source.
A direct HTTP integrator persists a machine request with one chosen publication ID before sending. The registration body remains PublicationCreate:
{ "id": "client-candidate-r1", "context_id": "lab-cpu", "descriptor": { "release_path": "/opt/enumeray/models/example/r1", "entrypoint": ["wrapper.py", "execute"], "environment": {} }, "definition": { "contract_version": 1, "model_identity": "example@v1", "wrapper_identity": "example-wrapper@v1", "runtime_identity": "author-example:python3-standard-library:1", "wrapper_protocol_version": 1, "dataset_identities": [], "input_schema": { "type": "object", "properties": {"value": {"type": "number"}}, "required": ["value"], "additionalProperties": false }, "output_schema": { "type": "object", "properties": {"doubled": {"type": "number"}}, "required": ["doubled"], "additionalProperties": false }, "examples": [{"name": "double-two", "inputs": {"value": 2}, "outputs": {"doubled": 4}}] }}Save it as publication-request.json, then use the administrator’s own active context grant:
enumeray api POST /api/v1/models/example/publications --file publication-request.jsonAfter an uncertain response, inspect that exact candidate ID and retry the same saved body/account. A new ID expresses a new candidate. This registers without activating; connector readiness, scientific trials/review and guarded explicit activation remain necessary. Author files and saved machine requests are not interchangeable. For guarded management changes, inspect the current generation immediately before saving the mutation body:
enumeray --json access policy example > policy.jsonGENERATION=$(jq -er '.generation' policy.json)jq -n --argjson generation "$GENERATION" \ '{mode: "request", visibility: "listed", expected_generation: $generation}' \ > policy-change.jsonenumeray api PUT /api/v1/models/example/access-policy --file policy-change.jsonOmitted or null visibility preserves the stored visibility; an explicit listed/unlisted value changes it independently of access mode. A generation conflict needs another inspection and a deliberate decision about the intervening change. An exact replay after a successful policy update also conflicts with the original generation and makes no further change. Use the command reference to understand api options and the endpoint reference for each management body.
Trial an exact candidate
Section titled “Trial an exact candidate”POST /api/v1/runs accepts purpose: "candidate_trial" in either the JSON body
or the multipart request part. Keep model_id, expected_publication_id and
inputs pinned to the candidate. Omitted purpose means standard, retaining the
ordinary current-publication/admission checks. Trial requests require
runs:create, models:manage, current model administration/execution access and
ownership of the candidate’s captured grant or an exact active publication_delegation_id issued by its holder. Delegated trial requests must include that ID; it is retained through claim, launch control and provenance.
Trials can use ready or published retained installations. They bypass public admission without changing it. Fresh trials reject retiring/unavailable installations; accepted work retains its exact identity through activation, replacement and delivery. The same idempotency key cannot switch between standard and trial purpose. Successful retries return the original receipt after authority or publication changes, using an active credential with the required scopes.
Administrator publication detail exposes trial_availability for the caller and
trial_evidence with counts, latest trial and latest successful trial references.
Use ordinary run inspection, logs, artifacts and provenance to assess results.
Readiness and execution success do not certify scientific correctness or activate
a candidate. Follow the author trial recipe.
Documentation 205dcb3116ea · public sources 8c70356d340f · built .Download documentation identity.