Skip to main content
The JS/TS exposes the Machine Markets API as a typed namespace on the existing PeaqosClient. Same client, additive surface. Each method maps to one HTTP route; the few routes without a method are listed under HTTP-only operations.
client.orchestration works only on a client constructed without tokenomics20. On a Tokenomics 2.0 client (tokenomics20 passed to the constructor, or TOKENOMICS_DEPLOYMENT_ID set in the environment that fromEnv() reads, which peaqos init writes), the machine, machine identity, agent pairing, machine agent, runtime endpoint, market search, market order, payment settlement, and purchase calls throw TokenomicsIntegrationUnavailableError before any request is sent. Skills, market services, policies, health, readiness, and audit-event calls still work. Pairing also needs an active, bonded Tokenomics 1.0 machine; see Scale.

Setup

Leave TOKENOMICS_DEPLOYMENT_ID unset in the .env this client reads:
Touching client.orchestration without orchestrationUrl configured throws OrchestrationConfigError. The namespace lazy-initialises and caches per client.

Configuration

Constructor form when not using env:
Transport constants:
  • API_BASE_PATH = "/api/v1", prepended to every path.
  • Timeouts: 30 s GET, 60 s POST/PATCH/PUT/DELETE.
  • A peaq-os-sdk-js/… User-Agent header.
No retry, no exponential backoff. See Pagination for the auto-paginated iterators.

Common envelopes

204 No Content resolves to void. validateListQuery rejects limit < 1 or limit > 500 with OrchestrationValidationError before the HTTP call.

Machines

Machine shape:

Machine identity challenges

Requests a server-issued challenge tied to a did:peaq:0x... or peaqos:machine:<id> identity reference. The DID controller signs item.message with EIP-191 personal_sign and submits the resulting { challengeId, signature } as identityProof when creating or updating the machine record.

Agent pairings

Pairing is challenge-based end to end:
  1. createAgentPairingChallenge returns a server-issued challenge keyed to agentAddress, agentProvider, agentRole, and optional agentDid.
  2. The item.message (EIP-191) with the key behind agentAddress.
  3. createAgentPairing accepts the proof in params.agentProof and returns the pairing with a signed HS256 session JWT in pairingToken. The token is returned once at create.
  4. createAgentPairingSession rotates the session token before expiry with a fresh proof. Required after any updateAgentPairing to the , since policy changes invalidate the current token’s delegationPolicyHash.
createAgentPairing and createAgentPairingSession return the pairingToken exactly once each. toJSON redacts the token to "[REDACTED]" so it does not leak through JSON.stringify. CreateAgentPairingRequest requires agentProof: { challengeId, signature } and accepts optional agentDid. delegationPolicy carries allowedServiceIds and deniedServiceIds next to the skill-level allow and deny lists.

Machine agents

enrollMachineAgent POSTs /machines/:machineId/agents/enrollment and returns the agent record with a one-time token. The declared type names it provisioningToken, but the server sends it as agentToken and the SDK passes the response through unchanged, so item.provisioningToken is undefined at runtime. Read it as (item as unknown as { agentToken: string }).agentToken until the SDK type is fixed. machineAgentHeartbeat sends no auth header: the agentToken rides in the request body.

Runtime endpoints

Upsert uses HTTP PUT. endpointBaseUrl is parsed with new URL(...) client-side; invalid URLs throw OrchestrationValidationError(field: "endpointBaseUrl", constraint: "valid URL").

Skills

Market services

searchMarket uses x-agent-pairing-token auth: the token rides in the second argument and is sent per call. getMarketSearch uses platform auth.

Market orders

listMarketOrders and getMarketOrder use platform auth; the four mutating calls require the agent’s pairingToken. executeMarketOrder returns execution.run and execution.outcome for a native run (execution.statusCode === 200). When the order resolves to an external handoff the server answers 202, the order moves to handoff, and the call throws OrchestrationApiError with code INVALID_RESPONSE_SHAPE. Catch it and read the handoff from the order:
ExecuteMarketOrderRequest carries only input, so it has no field for the payment headers x402-rail services take (x-payment, payment-signature, authorization, sign-in-with-x). Execute x402-rail orders with a direct POST /market/orders/:orderId/execute request carrying operatorCredentials.providers[providerKey] in the body, as described in the orders API reference.

Payment settlement

submitPaymentProof accepts EVM (transactionHash) and Solana (transactionSignature) shapes with verificationMode: "recorded" | "rpc". RPC verification cross-checks the ERC-20 Transfer log against expected token, payerAddress, payeeAddress, and amount.

Pagination

Six auto-paginated iterators:
Each *All accepts Omit<XxxOptions, "cursor">. The cursor is managed internally; filters and limit pass through on every page. For manual pagination, the underlying list* methods accept cursor and limit:

Policies

Cross-cutting policy records above and beyond a pairing’s delegation policy. Platform auth.
There is no getPolicy method. Read a single policy out of listPolicies.

Observability

checkHealth requests /api/v1/health, which returns 404 on the hosted orchestrator: the health route is GET /health at the host root, so call it over HTTP. listAuditEvents sends machineId, but the server ignores it and filters only on type, resourceType and resourceId; filter the returned events by machine yourself.

HTTP-only operations

These operations exist on the HTTP API (see Machine Markets API: Orchestration) and have no SDK method. Call them over HTTP.
  • Tasks: createTask, discoverTask, resolveTask, executeTask, getTask, listTasks
  • Graph: getMachineGraph, createGraphNode, updateGraphNode, deleteGraphNode, createGraphEdge, updateGraphEdge, deleteGraphEdge
  • Policies: getPolicy
  • Runs: listRuns, getRun
The SDK also exports CancelMarketOrderRequest and RetryMarketOrderRequest types, but the API has no cancel or retry route for market orders.

Errors

Five exported classes, all extend PeaqosError:
Switch on instanceof OrchestrationApiError then on err.code. Never parse err.message. Server code values exported as constants from @peaqos/peaq-os-sdk: ERROR_CODE_AUTH_REQUIRED, ERROR_CODE_AUTH_INVALID, ERROR_CODE_AGENT_AUTH_REQUIRED, ERROR_CODE_AGENT_AUTH_INVALID, ERROR_CODE_AGENT_AUTH_EXPIRED, ERROR_CODE_VALIDATION_ERROR, ERROR_CODE_NOT_FOUND, ERROR_CODE_MACHINE_NOT_ACTIVE, ERROR_CODE_MACHINE_NOT_ACTIVATED, ERROR_CODE_MACHINE_IDENTITY_EXISTS, ERROR_CODE_MACHINE_IDENTITY_IMMUTABLE, ERROR_CODE_MACHINE_IDENTITY_PROOF_REQUIRED, ERROR_CODE_MACHINE_IDENTITY_PROOF_INVALID, ERROR_CODE_MACHINE_IDENTITY_PROOF_EXPIRED, ERROR_CODE_PEAQOS_IDENTITY_UNAVAILABLE, ERROR_CODE_AGENT_PAIRING_PROOF_REQUIRED, ERROR_CODE_AGENT_PAIRING_PROOF_INVALID, ERROR_CODE_AGENT_PAIRING_PROOF_EXPIRED, ERROR_CODE_AGENT_PAIRING_UNAVAILABLE, ERROR_CODE_AGENT_PAIRING_REQUIRED, ERROR_CODE_AGENT_PAIRING_INACTIVE, ERROR_CODE_AGENT_POLICY_DENIED, ERROR_CODE_AGENT_SPEND_LIMIT_EXCEEDED, ERROR_CODE_AGENT_DAILY_LIMIT_EXCEEDED, ERROR_CODE_QUOTE_EXPIRED, ERROR_CODE_ORDER_CLOSED, ERROR_CODE_ORDER_NOT_DELIVERED, ERROR_CODE_PAYMENT_REQUIRED, ERROR_CODE_PAYMENT_RPC_REQUIRED, ERROR_CODE_PAYMENT_RPC_ERROR, ERROR_CODE_PAYMENT_TX_FAILED, ERROR_CODE_PAYMENT_NOT_MINED, ERROR_CODE_PAYMENT_TRANSFER_NOT_FOUND, ERROR_CODE_EXECUTION_UNSUPPORTED, ERROR_CODE_ENDPOINT_UNREACHABLE. Proof and credential types:
MarketPaymentRailType is "not-required" | "wallet" | "xvv42" | "x402" | "vault-stripe" | "escrow" | "offchain-record" | "external" | "onchain-escrow" | "wdk-usdt-transfer". The transport synthesises BAD_RESPONSE (non-JSON error body) and INVALID_RESPONSE_SHAPE (envelope mismatch) inside OrchestrationApiError when the server response is malformed.

Credential handling

Three auth modes per call:
  • Platform (x-api-key): set once on the client via apiKey, sent on every call by default.
  • Agent pairing (x-agent-pairing-token): passed per call as an explicit argument to market search, the order mutations, and the payment settlement calls. The SDK does not store or rotate it.
  • None: used only by machineAgentHeartbeat (token rides in the body).
sanitizeBody() redacts any body field whose name contains token, key, secret, password, credential, or auth (case-insensitive) before attaching the body to an error. Redaction is recursive into nested objects.