Product Demo Docs Blog About Contact Sign in Sign up

Docs

Submit verified-inference jobs in one Python call. Get back numpy embeddings and a tamper-proof receipt that proves the result is correct. Powered by the cyberian-client package.

Overview

You name a model, send your inputs, get back outputs and a tamper-proof receipt. The platform handles execution, independent verification, and the cryptographic attestations that make the result auditable.

  • One call: submit_and_wait(model=…, inputs=[…]) returns a numpy array and a receipt.
  • Typed exceptions: distinguish auth, quota, rate-limit, verification failures.
  • Numpy outputs: embeddings come back as np.ndarray(shape=(N, D), dtype=float32).
  • Auditable receipts: every result is anchored in Merkle roots that you can validate offline.

Install

Python 3.9+ required.

pip install cyberian-client

View on PyPI: pypi.org/project/cyberian-client and see version history, package hashes, release feed.

Authenticate

Get a key from signup. Pass it to the client constructor or set CYBERIAN_API_KEY in your environment.

from cyberian import Client

client = Client(api_key="cyb_yourlabel_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
# or: client = Client()  # reads CYBERIAN_API_KEY from env
Keep keys secret. Never commit them to git. Use environment variables, a secrets manager, or your CI provider's secret store.

Submit your first job

The simplest call is submit_and_wait - it submits, polls until settled, then fetches the receipt and the output array.

from cyberian import Client

client = Client()

texts = [
    "The quick brown fox jumps over the lazy dog.",
    "Cyberian Systems verifies AI inference end-to-end.",
    "Merkle receipts make outputs auditable.",
]

result = client.submit_and_wait(
    model="bge-large-v1.5",
    inputs=texts,
)

print("Job:", result.job["id"])
print("Receipt:", result.receipt["receipt_id"])
print("Output shape:", result.embeddings.shape)  # (3, 1024)
print("Output dtype:", result.embeddings.dtype)  # float32

Step-by-step (mirrors the REST chain)

The same five calls the REST Typical flow walks through, expressed as SDK methods. Use this when you want explicit control over each step (e.g. inspecting the unsettled job, separating the verification pass for an audit log).

# 1. submit a job
job = client.submit_job(model="bge-large-v1.5", inputs=texts)
print(job["id"], job["status"])  # EXECUTING

# 2. block until terminal (SETTLED / FAILED / REFUNDED)
settled = client.wait_for_completion(job["id"], timeout_sec=600)

# 3. fetch the slim Merkle receipt
receipt = client.get_receipt(settled["receipt_id"])

# 4. server-side verification pass — recomputes every hash
check = client.verify_receipt(settled["receipt_id"])
assert check["valid"], check["errors"]

# 5. pull the embeddings (reshapes via response headers for you)
embeddings = client.get_job_output(settled["id"])  # np.ndarray(N, D)

Models

Every job names a model (model="..."). To list the models enabled for your account:

info = client.list_models()
print(info["models"])

The platform is model-agnostic. Need a model that isn't enabled for you? Email support@cyberiansystems.ai with the model reference (e.g. a Hugging Face URL). Onboarding a new model is a configuration step on our side - no code change on yours.

Verifying a receipt

Every settled job produces a tamper-proof receipt that anchors the inputs, the outputs, and the verification attestation in cryptographic Merkle roots. You can re-check it offline:

receipt = client.get_receipt(result.receipt["receipt_id"])
verified = client.verify_receipt(receipt["receipt_id"])
assert verified["valid"] is True
print(verified["checks"])  # every check should be True

If any byte of the receipt is mutated, the verifier returns valid=False with details about why - that's the audit trail your customers (or regulators) can rely on.

Receipt fields

FieldWhat it is
receipt_idUnique receipt identifier.
job_idWhich job this receipt attests.
spec_hashOpaque hash of the execution specification used.
inputs_rootMerkle root over the inputs you submitted.
outputs_rootMerkle root over the outputs that were produced.
verification_attestationMerkle root committing to the independent verification work.
executor_attestation_idsOpaque IDs identifying the compute providers involved.
issued_atISO-8601 timestamp of issuance.
receipt_hashSelf-referential SHA-256 - what verify_receipt recomputes.

Verification as a Service

If you run inference on your own infrastructure and just need an independent attestation, use the VaaS endpoint. You submit your inputs and the SHA-256 of the outputs you produced; the platform independently verifies and issues a receipt.

import hashlib

# Compute SHA-256 of your output bytes (numpy array → bytes → sha256)
my_outputs_hash = hashlib.sha256(my_embeddings.tobytes()).hexdigest()

receipt = client.verify_outputs(
    model="bge-large-v1.5",
    inputs=texts,
    claimed_output_commitment=my_outputs_hash,
)
# Raises VerificationFailedError if our independent verification disagrees.

Account

client.get_account() returns a single dict describing your account, current usage, and the keys on file. The shape:

FieldMeaning
account_idUUID of your account.
nameDisplay name.
emailAccount email.
usernameAccount username.
email_verified_atISO-8601 timestamp, or null if not yet verified.
tierAssigned tier (e.g. "free").
effective_tierTier currently being charged against (changes when a trial expires).
subscription_status"trial" | "active" | "none".
trial_started_atISO-8601 timestamp.
trial_ends_atISO-8601 timestamp.
chunks_consumed_periodChunks consumed in the current period.
chunks_period_started_atISO-8601 timestamp of the current period's start.
limitsObject with the caps for the current effective tier - see below.
keysArray of API-key descriptors - see below.

limits

FieldMeaning
chunks_per_periodCap on chunks per period.
period_length_daysPeriod length, in days.
chunks_per_dayDaily chunk cap.
chunks_per_minuteSustained per-minute cap.
max_chunks_per_requestPer-request chunk cap.
max_inputsMaximum number of inputs allowed in one request.

keys[i]

FieldMeaning
key_id12-char prefix - pass this to revoke_key.
labelLabel you gave the key at creation.
created_atISO-8601 timestamp.
last_used_atISO-8601 timestamp, or null if never used.
revoked_atISO-8601 timestamp, or null if active.

All timestamps are UTC ISO-8601 strings.

Errors and retries

The client raises typed exceptions you can catch granularly:

ExceptionCauseRecommended action
AuthErrorInvalid or revoked API keyRe-issue key on the account page
TrialExpiredErrorTrial window passedEmail us to upgrade or extend
QuotaErrorPeriod or daily chunk quota hitWait until reset, or request more
RateLimitErrorPer-minute throughput exceededBack off; the SDK exposes retry_after
ServiceBusyErrorQueue depth or capacity hitRetry with backoff
JobFailedErrorOne or more chunks failed verificationInspect err.failed_chunks
VerificationFailedErrorReceipt did not verify offlineTreat output as untrusted
NetworkErrorTransport-level error (no HTTP response)wait_for_completion retries automatically; elsewhere, retry with backoff
ApiErrorOther 4xx/5xxInspect err.status and err.body
from cyberian import Client, RateLimitError, QuotaError

client = Client()

try:
    result = client.submit_and_wait(model="bge-large-v1.5", inputs=texts)
except RateLimitError as e:
    time.sleep(e.retry_after)
except QuotaError:
    print("Trial chunks exhausted - email us to extend.")

Trial limits

  • 14 days from email verification (not signup — the clock starts when you click the confirmation link)
  • 400 chunks per trial period
  • 100 chunks per day
  • 60 chunks per minute sustained
  • 100 chunks max per request, up to 1,000 input texts per request

Limits beyond the trial are quoted on request - email support@cyberiansystems.ai.

Client reference

Constructor

Client(api_key: str | None = None)

If api_key is omitted, the client reads CYBERIAN_API_KEY from the environment.

Methods

MethodReturnsDescription
submit_job(model, inputs)dictSubmit a job. Returns {"id", "status", "chunk_count", ...}.
get_job(job_id)dictFetch current job state.
wait_for_completion(job_id, timeout_sec=600)dictWait until the job reaches SETTLED, FAILED, or timeout.
get_job_output(job_id)np.ndarrayOutput tensor, dtype float32, shape (N, D).
get_receipt(receipt_id)dictThe slim public receipt - see "Receipt fields" above.
verify_receipt(receipt_id)dictValidate the receipt - {"valid", "checks", "errors"}.
submit_and_wait(model, inputs)JobResultOne-shot convenience.
verify_outputs(model, inputs, claimed_output_commitment)dictVaaS path - receipt for outputs you produced.
list_models()dictModels enabled for your account.
get_account()dictProfile, usage counters, key list.

JobResult

@dataclass
class JobResult:
    job:           dict       # final job dict from /jobs/:id
    receipt:       dict       # the slim public receipt
    embeddings:    np.ndarray # float32 tensor, shape (N, D)
    verification:  dict | None  # {"valid", "checks", "errors"} or None

Support

Questions, bug reports, upgrade requests: support@cyberiansystems.ai.