VORQ Docs
Reference

Provider API

Every /evm/* route, for the deployment, the job book, provider operations, asks, providers and the allowlist.

Routes under /evm/*. The read routes are public and used by clients too; the write routes relay provider-signed messages. Encoding, headers, paging and body limits are in API conventions; the error envelope and retry rule are in Errors.

Deployment

GET /evm/chain

The deployment parameters a client or provider needs to sign.

Auth: public · Index-backed: no (reads the chain)

Response 200

{
  "chain_id": 84532,
  "contracts": {
    "job_registry": "0x…",
    "provider_registry": "0x…",
    "ask_registry": "0x…",
    "usdc": "0x…"
  },
  "decimals": 6,
  "token_domain": { "name": "…", "version": "…" },
  "gas_price": "1000000",
  "head_block": "12345678",
  "block_time_ms": 2000,
  "fee_bps": 100
}
FieldMeaning
contracts.usdcThe payment token's address.
decimalsThe payment token's decimals.
token_domainThe payment token's EIP-712 name and version, for signing the payment.
gas_priceThe chain's current gas price, in wei.
head_blockThe chain head the node sees.
block_time_msThe node's poll interval.
fee_bpsThe protocol fee, in basis points.

Errors: 503 chain_unreachable or relay_unavailable (config_read).

Job book

GET /evm/jobs

The job book, filtered. With free=N it is also the provider's poll.

Auth: public; a provider session with free · Index-backed: yes · Paged: yes

QueryMeaning
stateOpen, Claimed, Settled or Cancelled. Cancelled means every ended job: cancelled, expired, failed or reclaimed.
modelA model_id.
providerA provider id: jobs claimed by it.
ownerAn owner address.
min_rate_in, min_rate_outOnly jobs with rates at or above these (decimal integers).
posted_beforeOnly jobs posted at or before this block.
orderoldest (default, by posting block) or newest.
freeProvider poll: lease up to this many jobs. See below.

Response 200

{
  "jobs": [
    {
      "job_id": "0x…", "owner": "0x…", "c": "0x…",
      "model_id": "3", "sla_secs": "3600", "designated": "0",
      "rate_in": "1500", "rate_out": "6000", "units_in": "1200", "units_out": "800",
      "expires_at": "1786003600", "state": 0, "ended_because": 0,
      "provider_id": "0", "claimed_at": "0", "completion_tok": "0",
      "task_cid": "bafy…", "result_cid": null, "posted_block": "12345600"
    }
  ],
  "as_of_block": "12345672"
}

state and ended_because are as in Job lifecycle; an open job past expires_at reads as 3 / 5. provider_id, claimed_at and completion_tok are "0" until claimed or settled.

Provider poll. With free=N (0–4294967295), the request needs a provider session, state=Open and a model in the catalog. The node records the provider as live for that model with N free slots, leases it up to N of the oldest matching jobs it may claim (open bids, or designated to it) for MATCH_LEASE_MS, counting leases it already holds, and returns only the jobs it holds. See Matching and leases. Without free, the session is ignored.

On a coordinator whose escrow has lost keys, open undesignated jobs posted before its current key custody are left out of the book.

Errors

StatuscodeCause
400nullA bad filter; free without state=Open or model; a model not in the catalog.
401invalid_sessionfree without a valid session.
403not_registeredfree with a session that is not a provider session.
curl -s "https://api.vorq.co/evm/jobs?state=Open&model=3&free=4" \
  -H "authorization: Bearer $TOKEN"

GET /evm/jobs/summary

Totals for one owner, overall and per model.

Auth: public · Index-backed: yes

QueryMeaning
ownerRequired. An owner address.

Response 200

{
  "jobs": "12", "completed": "10", "priced": "12", "escrowed": "91000",
  "by_model": [{ "model_id": "3", "jobs": "12", "completed": "10", "priced": "12", "escrowed": "91000" }],
  "as_of_block": "12345672"
}
FieldMeaning
jobsAll jobs by this owner.
completedSettled jobs.
pricedJobs whose rates are whole numbers.
escrowedThe sum of cap over priced jobs.

GET /evm/jobs/{job_id}

One job in the book's shape, plus as_of_block.

Auth: public · Index-backed: yes

Errors: 400 for a malformed id; 404 for an unknown job.

Provider operations

POST /evm/ops

Relay one signed provider op. The coordinator verifies the signature, simulates the transaction, sends it and waits for the receipt.

Auth: session (any address; the op signature is the authority) · Index-backed: no · Body limit: 20 MiB

Request: a flat object with op, signature (the provider wallet's signature over the op's signed message) and the op's fields.

opFieldsSigned message
claimjob_id, issued_atClaim
settlejob_id, completion_tok, issued_at, and exactly one of result (the sealed result, base64, non-empty) or result_cid (the vorq.cid of a result upload by this session's address)Settle
failjob_id, issued_atFail
set_identitybox_key (bytes32), evidence (hex bytes, at most 32 768), issued_atSetIdentity
request_capacityn (uint32), issued_atRequestCapacity
{ "op": "claim", "job_id": "0x…", "issued_at": 1786000000, "signature": "0x…" }

claim, settle and fail need issued_at within ±600 seconds of the node's clock. set_identity and request_capacity need issued_at greater than the last accepted one for that op and at most one hour ahead.

Response 201

{ "tx_hash": "0x…", "status": "success", "block_number": "12345678", "result_cid": "bafy…" }

result_cid is present on settle only: the IPFS CID the result was stored under.

Errors

StatusBody or codeCause
400result_required, result_ambiguous, unknown_result, or nullA malformed op, or a missing, doubled or unknown result.
401invalid_sessionNo valid session.
403type invalid_op_signatureThe signature does not recover to a registered provider.
409{"ok": false, "reason": "<ContractError>"}The chain refuses the op, for example StaleOp, NotOpen, AtCapacity, SlaExpired. When reason is unknown, raw carries the revert data. x-vorq-retryable: false.
429, 503, 504See Errors. A 504 message names the route to poll.

POST /evm/simulate/claim

An advisory check before signing a claim. It reads the chain, not the index, so it is accurate while the index lags.

Auth: public · Index-backed: no

Request

{ "job_id": "0x…", "address": "0x<provider wallet>" }

Response 200

{ "ok": false, "reason": "NotDesignated" }

{"ok": true}, or the first failing check, in the contract's order: UnknownJob, NotOpen, UnknownProvider, NotListed, ModelNotAllowed, NotDesignated, AtCapacity. It does not check the payment, the signature or the ±600-second window; POST /evm/ops simulates the real transaction.

Asks

PUT /evm/asks

Publish a signed ask snapshot to the AskRegistry. See Publish asks.

Auth: session (any address; the snapshot signature is the authority) · Index-backed: no · Body limit: 32 KiB

Request

{
  "snapshot": {
    "provider_id": 7,
    "signed_at": 1786000000,
    "quotes": [{ "model_id": 3, "sla": 3600, "rate_in": "1500", "rate_out": "6000" }]
  },
  "signature": "0x…"
}
FieldRule
snapshot.provider_idThe signer's provider id.
snapshot.signed_atNewer than the provider's latest snapshot; at most one hour ahead of the node's clock.
snapshot.quotesAt most 64. Each sets the ask for its (model_id, sla); both rates 0 withdraws it.
signatureThe provider wallet's AskSnapshot signature.

Response 200: after the publication is mined and confirmed.

{ "provider_id": "7", "signed_at": "1786000000", "published": true, "tx_hash": "0x…" }

Errors

StatuscodeCause
400nullA malformed snapshot; signed_at too far ahead.
401invalid_sessionNo valid session.
403invalid_signatureThe signature does not recover over the snapshot.
403not_registeredThe signer is not a registered provider.
403provider_mismatchThe signer operates a different provider than snapshot.provider_id.
409stale_snapshotsigned_at is not newer than the provider's latest.
409supersededA newer snapshot is already on chain.
503publication_skippedMined, but the chain recorded no publication. Retry.
504tx hashNo receipt within 60 seconds. The snapshot is stored; check GET /evm/asks rather than pushing it again.

GET /evm/asks

Published asks of listed providers.

Auth: public · Index-backed: yes · Paged: yes

QueryMeaning
modelOnly this model_id.

Response 200

{ "asks": [{ "provider_id": "7", "model_id": "3", "sla": "3600", "rate_in": "1500", "rate_out": "6000" }], "as_of_block": "12345672" }

GET /evm/asks/floors

The lowest ask per (model_id, sla) across listed providers, for catalog models. rate_in and rate_out are each minimised on their own, so a floor row may combine two providers' rates.

Auth: public · Index-backed: yes · Paged: yes

QueryMeaning
modelOnly this model_id.
slaOnly this SLA, in seconds.

Response 200

{ "floors": [{ "model_id": "3", "sla": "3600", "rate_in": "1200", "rate_out": "5000" }], "as_of_block": "12345672" }

Providers and catalog

GET /evm/providers

Registered providers, by id.

Auth: public · Index-backed: yes · Paged: yes

Response 200

{
  "providers": [
    {
      "provider_id": "7", "operator": "0x…", "box_key": "0x…", "evidence": {},
      "listed": true, "reputation": "1000",
      "allow_all_models": false, "allowed_models": ["3"],
      "capacity": "12", "active_jobs": "2"
    }
  ],
  "as_of_block": "12345672"
}
FieldMeaning
operatorThe provider's wallet address.
box_keyThe X25519 key designated orders are sealed to; null until set.
evidenceThe identity evidence published with set_identity, as JSON, or null.
reputation100–1000.
capacityEffective capacity: max(1, reputation × min(requested, ceiling) / 1000).
active_jobsJobs it currently holds claimed.

GET /evm/providers/{id}

One provider plus as_of_block.

Auth: public · Index-backed: yes

Errors: 400 for an id that is not a uint32; 404 for an unknown provider.

GET /evm/models

The model catalog; the same body as GET /v1/models.

GET /evm/allowlist

Entries of the contracts' attestation allowlist.

Auth: public · Index-backed: yes · Paged: yes

Response 200

{ "entries": [{ "key": "0x…", "status": 1, "entry": {} }], "as_of_block": "12345672" }

On this page