VORQ Docs
Reference

Escrow API

The escrow routes, GET /key, POST /release and POST /handover.

The escrow routes exist on every coordinator. On one with ESCROW_MODE=off they answer 403 with code: "escrow_unavailable" (not retryable). They do not read the index, so they keep answering while it catches up. See Escrow and key release.

GET /key

The public key a client seals an open bid's seed to.

Auth: public · Index-backed: no

Response 200

{
  "escrow_public_key": "<64 hex characters, no 0x>",
  "evidence": { "type": "static-coordinator-v1", "report_data": "<64 hex characters>", "debug": false, "release": 1 },
  "issued_at": 1786000000
}
FieldMeaning
escrow_public_keyX25519 public key, hex without 0x.
evidence.typestatic-coordinator-v1 in production mode; mock-coordinator-v1 in development mode, which also carries measurement, tcb and quote.
evidence.report_datasha256(escrow_public_key ‖ utf8("vorq-coordinator-escrow-v1")), hex.
evidence.releaseThe node's RELEASE_ORDINAL.
issued_atThe node's clock, Unix seconds.

Errors

StatuscodeCause
403escrow_unavailableThis coordinator hosts no escrow.
503escrow_key_unmintedA joining development-mode instance holds no key yet. Retryable.
curl -s https://api.vorq.co/key

POST /release

Release an open-bid job's payload key to the provider holding its claim.

Auth: public (the signature and the chain are the authority) · Index-backed: no · Body limit: 2 KiB

Request

{
  "job_id": "0x…",
  "seed_wrap": "<base64, 80 bytes>",
  "ct_hash": "0x<keccak256(ciphertext)>",
  "response_pubkey": "<64 hex characters, no 0x>",
  "issued_at": 1786000000,
  "signature": "0x…"
}
FieldRule
job_idThe claimed job.
seed_wrapThe container's 80-byte seed_wrap, canonical padded base64.
ct_hashkeccak256 of the container's ciphertext.
response_pubkeyA 32-byte X25519 public key, hex without 0x, to seal the answer to.
issued_atUnix seconds, within ±600 of the node's clock.
signatureThe claiming provider wallet's Release signature.

The node reads the job from the chain and requires that it is Claimed, that seed_wrap and ct_hash reproduce its commitment, and that the signer is the registered wallet of the provider that claimed it.

Response 200

{ "dek_sealed": "<base64>" }

The job's payload key (see Key derivation), sealed to response_pubkey.

Errors

StatuscodeCause
400stale_issued_atissued_at outside ±600 seconds.
400bad_containerMalformed seed_wrap or ct_hash.
400wrap_mismatchseed_wrap and ct_hash do not reproduce the job's commitment.
400unseal_failedNo key this escrow holds opens the wrap. Fail the job within 300 seconds of the claim.
400nullA malformed job_id, response_pubkey or issued_at.
403wrong_walletThe signature is malformed, or not from the provider holding the claim.
403escrow_unavailableThis coordinator hosts no escrow.
404no_claimThe chain has no such job.
409not_claimedThe job is not in the Claimed state.
410escrow_key_lostDevelopment mode only: the job was sealed to a key no live instance holds. Fail it within 300 seconds of the claim.
503chain_unreachable, relay_unavailable (job_read, provider_id_read)The chain read failed. Retryable.

POST /handover

Key transfer between development-mode (ESCROW_MODE=mock) instances. It answers 403 escrow_unavailable when the escrow is off and 403 escrow_handover_disabled in production mode, where every instance already derives the same key.

Auth: an operator signature in the body · Index-backed: no · Body limit: 4 KiB

Request: {evidence, channel_pubkey, issued_at, operator_signature}, where operator_signature is a HandoverAuth(bytes32 channelPubkey,uint64 issuedAt) signature in the VORQ Escrow domain by an OPERATOR_KEY the holder accepts.

Response 200: {keys_sealed, key_count, holder_release}, the held keys sealed to channel_pubkey.

Errors: stale_issued_at, bad_binding, debug_evidence, stale_release, bad_operator_signature, operator_not_authorized, not_allowlisted, tombstoned, escrow_unavailable, escrow_handover_disabled, and retryable chain_unreachable / relay_unavailable (allowlist_status_read).

On this page