> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Orchestration (JavaScript)

> client.orchestration.* namespace on the JS/TS SDK: machines, agent pairings, machine agents, runtime endpoints, skills, market services, market search.

export const G = {
  onchain: {
    id: "onchain",
    cat: "chain-infra",
    term: "On-chain vs off-chain",
    def: "On-chain means written to the shared public ledger every machine agrees on: permanent and readable by anyone. Off-chain means kept on a normal private server instead."
  },
  blockchain: {
    id: "blockchain",
    cat: "chain-infra",
    term: "Chain / blockchain",
    def: "A shared, tamper-resistant public database maintained by a whole network of computers with no single owner. Different chains are separate such networks."
  },
  peaqChain: {
    id: "peaqChain",
    cat: "chain-infra",
    term: "peaq chain",
    def: "The machine-focused blockchain peaqOS uses as home base for identity and credit records."
  },
  transaction: {
    id: "transaction",
    cat: "chain-infra",
    term: "Transaction (tx) / tx hash",
    def: "A single signed request that changes the ledger. Its hash is a unique, receipt-like ID you can use to look it up later."
  },
  rpcUrl: {
    id: "rpcUrl",
    cat: "chain-infra",
    term: "RPC URL / endpoint",
    def: "The network address your code calls to read from or write to a chain, like the base URL of the chain's API server."
  },
  mainnet: {
    id: "mainnet",
    cat: "chain-infra",
    term: "Mainnet / testnet (agung)",
    def: "Mainnet is the real, live network where tokens have real value. Testnet is a free practice copy with worthless tokens; peaq's is called agung."
  },
  evm: {
    id: "evm",
    cat: "chain-infra",
    term: "EVM / EVM-compatible",
    def: "The Ethereum Virtual Machine: the standard runtime many chains share, so the same 0x... addresses and tools work across all of them. peaq is EVM-compatible."
  },
  node: {
    id: "node",
    cat: "chain-infra",
    term: "Node (RPC node)",
    def: "A server running the blockchain software that holds a copy of the ledger and answers queries. NOT a ROS 2 node, despite the shared word."
  },
  chainId: {
    id: "chainId",
    cat: "chain-infra",
    term: "Chain ID",
    def: "A number that uniquely labels a chain so software doesn't confuse networks (peaq is 3338, Base is 8453)."
  },
  precompile: {
    id: "precompile",
    cat: "chain-infra",
    term: "Precompile",
    def: "A built-in function baked into the chain at a fixed address that acts like a contract but runs as faster native code. The batch one bundles several actions into one all-or-nothing transaction."
  },
  dataHash: {
    id: "dataHash",
    cat: "chain-infra",
    term: "Data hash (keccak256)",
    def: "A short, fixed-length fingerprint of a file, stored on-chain instead of the file itself, so data can be verified later while the raw data stays off-chain."
  },
  depin: {
    id: "depin",
    cat: "chain-infra",
    term: "DePIN",
    def: "Decentralized Physical Infrastructure Network: a network of real-world machines built and run by many independent owners who earn for the work their machines do."
  },
  wallet: {
    id: "wallet",
    cat: "wallet-keys",
    term: "Wallet",
    def: "An account on the chain, identified by a public address, that holds a machine's funds and approves its actions. Really just a pair of keys, not a place money is stored."
  },
  keypair: {
    id: "keypair",
    cat: "wallet-keys",
    term: "Keypair",
    def: "The two matched secrets behind a wallet: a public address you can share, and a private key you keep secret that signs actions."
  },
  privateKey: {
    id: "privateKey",
    cat: "wallet-keys",
    term: "Private key",
    def: "The secret string that proves you control a wallet. Anyone who has it has full control, like a master password that can never be reset."
  },
  sign: {
    id: "sign",
    cat: "wallet-keys",
    term: "Sign / signature",
    def: "Using your private key to produce a cryptographic stamp proving you approved a specific action, without ever revealing the key."
  },
  signer: {
    id: "signer",
    cat: "wallet-keys",
    term: "Signer / signing identity",
    def: "The wallet whose private key authorizes an action: the account the network treats as the one taking it. NOT a file or an app."
  },
  address: {
    id: "address",
    cat: "wallet-keys",
    term: "Address (0x...)",
    def: "The public 0x... identifier of a wallet or contract you can freely share so others can send to it or look it up, like an account number."
  },
  eoa: {
    id: "eoa",
    cat: "wallet-keys",
    term: "EOA (externally owned account)",
    def: "A plain wallet controlled directly by a private key, as opposed to one controlled by code. Here, the account that IS the machine."
  },
  ows: {
    id: "ows",
    cat: "wallet-keys",
    term: "OWS / wallet vault",
    def: "An open standard for storing wallet keys in an encrypted local file (a vault) with a backup phrase, instead of a bare key in a text file."
  },
  passphrase: {
    id: "passphrase",
    cat: "wallet-keys",
    term: "Passphrase (OWS_PASSPHRASE)",
    def: "The password that unlocks the encrypted wallet vault so its key can be used to sign."
  },
  mnemonic: {
    id: "mnemonic",
    cat: "wallet-keys",
    term: "Mnemonic / seed phrase",
    def: "A list of 12 or 24 ordinary words that encodes a wallet's secret key, used to back it up and recover it. Whoever has the words controls the wallet."
  },
  derivation: {
    id: "derivation",
    cat: "wallet-keys",
    term: "Derivation path",
    def: "The deterministic recipe that turns one backup phrase into many specific keys and addresses, one per network or index."
  },
  challenge: {
    id: "challenge",
    cat: "wallet-keys",
    term: "Challenge (sign-to-prove)",
    def: "A login-style handshake: the server sends a random message, you sign it with your key, and the signature proves you control the account without sending the key."
  },
  eip191: {
    id: "eip191",
    cat: "wallet-keys",
    term: "EIP-191 / personal_sign",
    def: "A standard way to sign a plain message to prove you control an account, without sending any on-chain transaction."
  },
  did: {
    id: "did",
    cat: "identity",
    term: "DID / peaqID",
    def: "A globally unique, self-owned ID for a machine that lives on the chain and isn't issued by any single company. peaqID is peaq's version: did:peaq:<machine ID as a decimal> for an Economics 2.0 machine, did:peaq:0x<address> for a Tokenomics 1.0 machine or an operator."
  },
  register: {
    id: "register",
    cat: "identity",
    term: "Register a machine",
    def: "Putting a machine on the network for the first time, which gives it an ID, a DID, an ownership token, and a locked deposit. Under Economics 2.0 this is one activateMachine call signed by the machine's owner on peaq, or the seven-stage onboarding for a machine homed on Solana; registerMachine and registerFor are the older Tokenomics 1.0 calls."
  },
  machineId: {
    id: "machineId",
    cat: "identity",
    term: "Machine ID",
    def: "Your machine's handle in every later call. Under Economics 2.0 it is derived from the machine type and credential subject (a large uint256, written as a decimal string); Tokenomics 1.0 machines got a small sequential number."
  },
  ownerOperator: {
    id: "ownerOperator",
    cat: "identity",
    term: "Owner / operator",
    def: "The owner owns a machine; the operator runs it. They can be the same account (self-managed) or different (proxy-managed)."
  },
  proxyOperator: {
    id: "proxyOperator",
    cat: "identity",
    term: "Proxy operator",
    def: "One account that registers and manages many machines on behalf of their owners, so a fleet operator can handle a whole fleet from one wallet."
  },
  didAttributes: {
    id: "didAttributes",
    cat: "identity",
    term: "DID attributes",
    def: "Public name-value facts (a docs link, a data endpoint) attached to a machine's DID and stored on-chain for anyone to read. An Economics 2.0 machine sets them as service endpoints during activation; a Tokenomics 1.0 machine writes them in a separate transaction after registration."
  },
  pairing: {
    id: "pairing",
    cat: "identity",
    term: "Pairing / pairing token",
    def: "The verified link between an AI agent and a machine, set up by signing a challenge. The pairing token is the signed credential the agent sends with each request, like a temporary access badge."
  },
  hardwareAttestation: {
    id: "hardwareAttestation",
    cat: "identity",
    term: "Hardware attestation",
    def: "A tamper-resistant chip on the machine cryptographically vouching that it's genuine hardware, so its identity can't be faked in software. This is the Verify layer."
  },
  gas: {
    id: "gas",
    cat: "tokens-economics",
    term: "Gas",
    def: "The small fee, paid in the chain's token, that every action writing to the ledger costs, like a per-write transaction cost."
  },
  peaqToken: {
    id: "peaqToken",
    cat: "tokens-economics",
    term: "PEAQ (token)",
    def: "The peaq network's own token, used to pay gas fees and to lock up as the deposit when registering a machine."
  },
  gasStation: {
    id: "gasStation",
    cat: "tokens-economics",
    term: "Gas Station / faucet",
    def: "A peaq service that hands a brand-new, empty wallet a tiny starting amount of tokens so it can afford its first network fees. Gated by 2FA."
  },
  bond: {
    id: "bond",
    cat: "tokens-economics",
    term: "Bond",
    def: "PEAQ locked when a machine activates, proving skin in the game. Under Economics 2.0 it is priced per tier in USD and converted to PEAQ at the oracle rate, and it is not withdrawable; Tokenomics 1.0 machines locked a fixed 1 PEAQ. Bonded means the deposit is in place."
  },
  nft: {
    id: "nft",
    cat: "tokens-economics",
    term: "NFT",
    def: "A unique, one-of-a-kind ownership token recorded on the chain. Unlike a coin, no two are interchangeable."
  },
  mint: {
    id: "mint",
    cat: "tokens-economics",
    term: "Mint / minting",
    def: "Creating a brand-new token on the chain and assigning it to an owner, like stamping a fresh serial-numbered certificate into existence."
  },
  machineNft: {
    id: "machineNft",
    cat: "tokens-economics",
    term: "Machine NFT",
    def: "The unique token representing one specific physical machine. Under Economics 2.0 a peaq-homed machine has one ERC-721 in MachineRegistry and a Solana-homed machine has a native Machine account; transferring it transfers ownership of the machine. Under Tokenomics 1.0 it is a separate financial NFT that can be sold or bridged apart from the machine's identity."
  },
  identityNft: {
    id: "identityNft",
    cat: "tokens-economics",
    term: "Identity NFT",
    def: "Tokenomics 1.0 only: a non-transferable (soulbound) token minted automatically when a machine registered, representing its identity. Its token ID equals the machine ID. An Economics 2.0 machine has no separate identity NFT; its Machine NFT in MachineRegistry carries the identity."
  },
  tokenId: {
    id: "tokenId",
    cat: "tokens-economics",
    term: "Token ID",
    def: "The unique number identifying one specific token within a collection, like a serial number."
  },
  mcr: {
    id: "mcr",
    cat: "tokens-economics",
    term: "Machine Credit Rating (MCR)",
    def: "A creditworthiness score for a machine (a Moody's-style grade AAA down to NR, plus a 0-100 number) computed from its recorded earnings and activity. Like a credit score for a robot."
  },
  mcrApi: {
    id: "mcrApi",
    cat: "tokens-economics",
    term: "MCR API",
    def: "The public web service you call to fetch a machine's credit score and profile as JSON, and the one place a machine's monetization is switched on or off with a signed message. No login needed: reads are open, and the write is authorized by the signature itself."
  },
  provisioned: {
    id: "provisioned",
    cat: "tokens-economics",
    term: "Provisioned / NR (Not Rated)",
    def: "Early MCR statuses. Provisioned means registered and bonded but with too little history to score yet. NR means no grade, because the score is too low or the machine isn't bonded."
  },
  event: {
    id: "event",
    cat: "tokens-economics",
    term: "Event (revenue / activity)",
    def: "A recorded data point about a machine's work, submitted to the chain to feed its credit score. Revenue events report money earned; activity events report work with no money. NOT a ROS topic message."
  },
  trustLevel: {
    id: "trustLevel",
    cat: "tokens-economics",
    term: "Trust level",
    def: "A label on each submitted event saying how strongly its truth is backed: the machine's word (0), a checkable on-chain record (1), or tamper-proof hardware proof (2)."
  },
  escrow: {
    id: "escrow",
    cat: "tokens-economics",
    term: "Escrow",
    def: "Holding a buyer's payment in a neutral locked place until the service is delivered, then releasing it, so neither side has to trust the other first."
  },
  paymentRail: {
    id: "paymentRail",
    cat: "tokens-economics",
    term: "Payment rail",
    def: "The specific method or channel a payment moves through, like choosing card vs bank transfer vs a particular token."
  },
  x402: {
    id: "x402",
    cat: "tokens-economics",
    term: "x402",
    def: "A web payment standard where a server answers 'payment required' with exact instructions, and the buyer's wallet signs an authorization instead of sending a separate transaction. Built for machines and agents paying per request."
  },
  usdt: {
    id: "usdt",
    cat: "tokens-economics",
    term: "USDT",
    def: "A stablecoin token meant to hold a value of one US dollar, used to pay service providers without price swings."
  },
  fractionalize: {
    id: "fractionalize",
    cat: "tokens-economics",
    term: "Fractionalize (ERC-3643)",
    def: "Splitting ownership of one machine into many small tradable shares so multiple people can each own a piece. ERC-3643 is the regulated-securities token standard used to do it."
  },
  smartContract: {
    id: "smartContract",
    cat: "smart-contracts",
    term: "Smart contract / contract address",
    def: "A program deployed on the chain that runs exactly as written and that anyone can call, identified by its own 0x... address."
  },
  registryContracts: {
    id: "registryContracts",
    cat: "smart-contracts",
    term: "Registry contracts",
    def: "On-chain programs that each keep an official, lookup-able list. Under Economics 2.0, MachineRegistry tracks which machines exist, EventRegistry stores their events and MachineSubscription holds their bonds; under Tokenomics 1.0 these were IdentityRegistry, EventRegistry and IdentityStaking."
  },
  smartAccount: {
    id: "smartAccount",
    cat: "smart-contracts",
    term: "Smart account (ERC-4337)",
    def: "A programmable wallet controlled by code instead of a single key, so it can enforce rules like spending limits. A machine gets one through a separate deploySmartAccount call after activation."
  },
  submitEvent: {
    id: "submitEvent",
    cat: "smart-contracts",
    term: "submitEvent / batchSubmitEvents",
    def: "The calls that record one or many of a machine's revenue or activity entries onto the chain."
  },
  revert: {
    id: "revert",
    cat: "smart-contracts",
    term: "Revert",
    def: "When an on-chain call is rejected and fully undone because a rule was broken, leaving no changes and usually a named error."
  },
  soulbound: {
    id: "soulbound",
    cat: "smart-contracts",
    term: "Soulbound",
    def: "A token that can never be transferred or sold and stays permanently attached to one owner. The Tokenomics 1.0 Identity NFT is soulbound."
  },
  bridge: {
    id: "bridge",
    cat: "cross-chain",
    term: "Bridge / bridging",
    def: "Moving a token from one chain to another. Tokenomics 1.0 Machine NFTs can be bridged from peaq to Base through the SDKs (mainnet only); Economics 2.0 machines cannot be bridged or relocated yet."
  },
  base: {
    id: "base",
    cat: "cross-chain",
    term: "Base",
    def: "Another blockchain network (built by Coinbase). Tokenomics 1.0 Machine NFTs can be bridged to and from it. Paying fees on Base needs Base ETH."
  },
  omniChain: {
    id: "omniChain",
    cat: "cross-chain",
    term: "Omni-chain / cross-chain",
    def: "Working across many separate chains at once, so a machine's identity and credit created on peaq can be read or used on other chains."
  },
  homeChain: {
    id: "homeChain",
    cat: "cross-chain",
    term: "Home chain",
    def: "The chain where a record's canonical, authoritative copy lives. For a peaqOS machine that is peaq, or Solana for an Economics 2.0 machine created there; other chains hold mirrors. The subscription is booked on peaq either way; a Solana-homed machine pays its bond on Solana."
  },
  satelliteChain: {
    id: "satelliteChain",
    cat: "cross-chain",
    term: "Satellite chain",
    def: "A chain carrying a read-only, automatically synced mirror of home-chain records, so apps there can use them without crossing back to the home chain."
  },
  sourceChainId: {
    id: "sourceChainId",
    cat: "cross-chain",
    term: "sourceChainId / sourceTxHash",
    def: "Two fields recording which chain an action happened on and its hash there, so a cross-chain event can be traced back and verified."
  },
  machineAgent: {
    id: "machineAgent",
    cat: "general-web3",
    term: "Machine Agent",
    def: "A third-party AI program (Claude, OpenAI, a custom bot) paired to a machine and given limited permission to find, buy, and pay for services on its behalf."
  },
  delegationPolicy: {
    id: "delegationPolicy",
    cat: "general-web3",
    term: "Delegation policy",
    def: "The rules an owner gives an AI agent that cap how much it can spend per transaction and per day and which services it may use, so it transacts within guardrails."
  },
  machineMarkets: {
    id: "machineMarkets",
    cat: "general-web3",
    term: "Machine Markets / Service Registry",
    def: "peaqOS's marketplace where machines list services they offer (Service Registry) and where agents discover, order, pay for, and run services from others."
  },
  sdk: {
    id: "sdk",
    cat: "general-web3",
    term: "SDK (peaq-os-sdk)",
    def: "peaq's code library (Python and JS) you install to call all this functionality without writing low-level blockchain calls yourself."
  },
  stream: {
    id: "stream",
    cat: "data-stream",
    term: "Stream (Data-as-a-Service)",
    def: "The peaqOS function where a machine sells the data it generates: it signs the data, encrypts what's sensitive, and grants buyers access. Selling data, as opposed to selling capacity (that's Monetize)."
  },
  edgeAgent: {
    id: "edgeAgent",
    cat: "data-stream",
    term: "peaqOS Edge Agent",
    def: "Software that runs on the machine itself (as a ROS 2 node) and signs, encrypts, and ships the data it produces. The on-machine half of Stream."
  },
  dataPackage: {
    id: "dataPackage",
    cat: "data-stream",
    term: "Signed data package",
    def: "A bundle of machine data stamped with the machine's identity (DID, timestamp, sequence number) and a signature, so anyone can prove which machine produced it and that it wasn't altered."
  },
  dataEventMap: {
    id: "dataEventMap",
    cat: "data-stream",
    term: "Data Event Map",
    def: "The policy file a machine owner writes to control what streams out: which topics to read, which fields to keep, drop, or encrypt, and where the signed data goes."
  },
  chunk: {
    id: "chunk",
    cat: "data-stream",
    term: "Chunk",
    def: "A bounded, individually encrypted slice of a data stream (by time window or size). The unit a buyer actually purchases and decrypts."
  },
  chunkChain: {
    id: "chunkChain",
    cat: "data-stream",
    term: "Chunk chain",
    def: "A run of chunks linked in order, each referencing the one before it, so missing, reordered, or edited chunks are detectable. Tamper-evidence for a continuous stream."
  },
  manifest: {
    id: "manifest",
    cat: "data-stream",
    term: "Manifest",
    def: "A record describing a chunk: its hashes, storage location, and encryption details, without the data itself. The machine signs the chunk's encrypted data hash; buyers check the signature and hashes before trusting or buying."
  },
  envelopeEncryption: {
    id: "envelopeEncryption",
    cat: "data-stream",
    term: "Envelope encryption / key wrapping",
    def: "Encrypt the data once with a random key, then lock that key separately for each authorized reader. Granting a buyer access re-locks the key to their public key; the data itself is never re-encrypted."
  },
  accessGrant: {
    id: "accessGrant",
    cat: "data-stream",
    term: "Access grant",
    def: "What a buyer receives after paying: the chunk keys they bought, each locked to their public key. They unlock with their private key and decrypt only those chunks."
  },
  contextProvider: {
    id: "contextProvider",
    cat: "data-stream",
    term: "Context Provider",
    def: "A third party that buys machine data, normalizes it into datasets, and serves or resells it (for example, for AI training). The buyer side of Stream, such as DataHive."
  },
  computeProvider: {
    id: "computeProvider",
    cat: "monetize",
    term: "Compute provider",
    def: "A machine that rents out its processing power to a compute network. Instead of sitting idle, the machine runs other people's workloads and earns for it."
  },
  provisioningManifest: {
    id: "provisioningManifest",
    cat: "monetize",
    term: "Provisioning manifest",
    def: "A published, step-by-step install plan that turns a machine into a compute provider: the checks to run first, the commands to execute, and the probes that prove it worked. The machine pulls it on demand and runs it locally."
  },
  heartbeat: {
    id: "heartbeat",
    cat: "monetize",
    term: "Heartbeat",
    def: "A short signed 'I'm here' message a machine sends out at a regular interval. As long as heartbeats keep arriving, the machine counts as online; if they stop, it's marked offline automatically."
  },
  aggregator: {
    id: "aggregator",
    cat: "monetize",
    term: "Aggregator",
    def: "A network that pools capacity from many machines and sells it on, such as a decentralized compute marketplace. Machines connect to an aggregator, which then dispatches work to them."
  },
  machineWallet: {
    id: "machineWallet",
    cat: "monetize",
    term: "Machine wallet",
    def: "The wallet that belongs to the machine itself, separate from its owner's or operator's wallet. Earnings from the machine's work land here by default."
  },
  walrus: {
    id: "walrus",
    cat: "chain-infra",
    term: "Walrus",
    def: "A decentralized storage network where encrypted data chunks can be parked, referenced by walrus:// links. The data stays off the blockchain; only its reference and fingerprint are tracked on-chain."
  },
  solana: {
    id: "solana",
    cat: "cross-chain",
    term: "Solana",
    def: "A high-throughput blockchain. peaqOS wallets hold a Solana account and sign Solana transactions, machine-economy payments can settle there, and an Economics 2.0 machine can be homed there (identity, DID and NFT as Solana accounts, the bond paid on Solana and booked on peaq)."
  }
};

The JS/TS <Tooltip tip={G.sdk.def}>SDK</Tooltip> exposes the [Machine Markets API](/peaqos/api-reference/machine-markets-overview) 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](#http-only-operations).

<Warning>
  `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](/peaqos/functions/scale).
</Warning>

## Setup

Leave `TOKENOMICS_DEPLOYMENT_ID` unset in the `.env` this client reads:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
import 'dotenv/config';
import { PeaqosClient } from "@peaqos/peaq-os-sdk";

const client = PeaqosClient.fromEnv();
const { items } = await client.orchestration.listMachines({ limit: 20 });
```

Touching `client.orchestration` without `orchestrationUrl` configured throws `OrchestrationConfigError`. The namespace lazy-initialises and caches per client.

## Configuration

| Field | Env var (via `fromEnv()`) | Notes |
| :- | :- | :- |
| `orchestrationUrl` | `PEAQOS_ORCHESTRATION_URL` | Required to use the namespace. Must parse as `http:` or `https:`. With `verbose: true`, a non-loopback `http://` URL logs a warning. |
| `apiKey` | `PEAQOS_API_KEY` | Sent as `x-api-key` on platform-auth calls. Required only when the orchestrator enforces platform auth. |

Constructor form when not using env:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
new PeaqosClient({
  rpcUrl,
  privateKey,
  contracts,
  orchestrationUrl: "https://orchestration.peaq.xyz",
  apiKey: "...",
});
```

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](#pagination) for the auto-paginated iterators.

## Common envelopes

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ListResponse<T> = {
  readonly items: readonly T[];
  readonly nextCursor?: string;          // omitted when there is no next page
};

type ItemResponse<T> = {
  readonly item: Readonly<T>;
};

type ListQuery = {
  readonly limit?: number;               // 1..500, default 100
  readonly cursor?: string;              // opaque, omit on first page
};
```

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

## Machines

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listMachines(options?: {
  cursor?: string;
  limit?: number;
}): Promise<ListResponse<Machine>>

client.orchestration.createMachine(params: CreateMachineRequest)
  : Promise<ItemResponse<Machine>>

client.orchestration.getMachine(machineId: string)
  : Promise<ItemResponse<Machine>>

client.orchestration.updateMachine(machineId: string, params: UpdateMachineRequest)
  : Promise<ItemResponse<Machine>>
```

`Machine` shape:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type Machine = {
  readonly id: string;
  readonly displayName: string;
  readonly status: "draft" | "active" | "degraded" | "blocked" | "archived";
  readonly ownerId: string;
  readonly identityRef?: string | null;
  readonly identityProof?: {
    readonly method: "eip191";
    readonly identityRef: string;
    readonly signerAddress: string;
    readonly challengeId: string;
    readonly verifiedAt: string;
    readonly challengeExpiresAt: string;
    readonly controllerAddresses: readonly string[];
    readonly resolutionSource: "peaqos-mcr";
  } | null;
  readonly machineType: string;
  readonly runtimeProfile: string;
  readonly capabilities: readonly string[];
  readonly labels: Readonly<Record<string, string>>;
  readonly policyIds: readonly string[];
  readonly skillKeys: readonly string[];
  readonly createdAt: string;
  readonly updatedAt: string;
};
```

## Machine identity challenges

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.createMachineIdentityChallenge(
  params: CreateMachineIdentityChallengeRequest,
): Promise<ItemResponse<MachineIdentityChallengeResponse>>
```

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

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listAgentPairings(machineId: string, options?: ListAgentPairingsOptions)
  : Promise<ListResponse<AgentPairing>>

client.orchestration.createAgentPairingChallenge(
  machineId: string,
  params: CreateAgentPairingChallengeRequest,
): Promise<ItemResponse<AgentPairingChallengeResponse>>

client.orchestration.createAgentPairing(
  machineId: string,
  params: CreateAgentPairingRequest,
): Promise<ItemResponse<AgentPairing & { pairingToken: string }>>

client.orchestration.createAgentPairingSession(
  machineId: string,
  pairingId: string,
  params: CreateAgentPairingSessionRequest,
): Promise<ItemResponse<AgentPairing & { pairingToken: string }>>

client.orchestration.updateAgentPairing(
  machineId: string,
  pairingId: string,
  params: UpdateAgentPairingRequest,
): Promise<ItemResponse<AgentPairing>>

client.orchestration.revokeAgentPairing(machineId: string, pairingId: string)
  : Promise<void>
```

Pairing is challenge-based end to end:

1. `createAgentPairingChallenge` returns a server-issued challenge keyed to `agentAddress`, `agentProvider`, `agentRole`, and optional `agentDid`.
2. The <Tooltip tip={G.machineAgent.def}>Machine Agent</Tooltip> <Tooltip tip={G.sign.def}>signs</Tooltip> `item.message` (EIP-191) with the <Tooltip tip={G.wallet.def}>wallet</Tooltip> 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 <Tooltip tip={G.delegationPolicy.def}>delegation policy</Tooltip>, 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

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.enrollMachineAgent(
  machineId: string,
  params?: EnrollMachineAgentRequest,
): Promise<ItemResponse<MachineAgent & { provisioningToken: string }>>

client.orchestration.machineAgentHeartbeat(
  params: MachineAgentHeartbeatRequest,
): Promise<MachineAgentHeartbeatResponse>
```

`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

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listRuntimeEndpoints(machineId: string, options?: ListRuntimeEndpointsOptions)
  : Promise<ListResponse<RuntimeEndpoint>>

client.orchestration.getRuntimeEndpoint(machineId: string, providerKey: string)
  : Promise<ItemResponse<RuntimeEndpoint>>

client.orchestration.upsertRuntimeEndpoint(
  machineId: string,
  providerKey: string,
  params: UpsertRuntimeEndpointRequest,
): Promise<ItemResponse<RuntimeEndpoint>>

client.orchestration.deleteRuntimeEndpoint(machineId: string, providerKey: string)
  : Promise<void>
```

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

## Skills

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listSkills(options?: {
  scope?: SkillScope;
  direction?: SkillDirection;
  source?: SkillSource;
}): Promise<ListResponse<SkillSummary>>

client.orchestration.getSkill(skillKey: string)
  : Promise<ItemResponse<SkillSummary>>

client.orchestration.getSkillManifest(skillKey: string)
  : Promise<ItemResponse<SkillManifest>>
```

## Market services

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listMarketServices(options?: {
  machineId?: string;
  serviceType?: ServiceType;
  executionMode?: ExecutionMode;
  providerKey?: string;
}): Promise<ListResponse<MarketService>>

client.orchestration.getMarketService(
  serviceId: string,
  options?: { machineId?: string },
): Promise<ItemResponse<MarketService>>
```

## Market search

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.searchMarket(
  params: MarketSearchRequest,
  pairingToken: string,
): Promise<ItemResponse<MarketSearch>>

client.orchestration.getMarketSearch(searchId: string)
  : Promise<ItemResponse<MarketSearch>>
```

`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

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listMarketOrders(
  options: ListMarketOrdersOptions,        // { machineId, cursor?, limit? }
): Promise<ListResponse<MarketOrder>>

client.orchestration.createMarketOrder(
  params: CreateMarketOrderRequest,        // { machineId, agentPairingId, serviceId, searchId?, quoteId?, operation?, input?, budget?, providerCredentials? }
  pairingToken: string,
): Promise<ItemResponse<MarketOrder>>

client.orchestration.getMarketOrder(
  orderId: string,
): Promise<ItemResponse<MarketOrder>>

client.orchestration.executeMarketOrder(
  orderId: string,
  params: ExecuteMarketOrderRequest,       // { input? }
  pairingToken: string,
): Promise<ExecuteMarketOrderResponse>     // discriminated union

client.orchestration.confirmMarketOrder(
  orderId: string,
  pairingToken: string,
): Promise<ConfirmMarketOrderResponse>     // { order, payment: MarketPayment | null }

client.orchestration.disputeMarketOrder(
  orderId: string,
  params: DisputeMarketOrderRequest,       // { reason, evidence? }
  pairingToken: string,
): Promise<DisputeMarketOrderResponse>     // { order, payment, dispute }; payment → "frozen"
```

`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:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
import 'dotenv/config';
import { OrchestrationApiError, PeaqosClient } from "@peaqos/peaq-os-sdk";

const client = PeaqosClient.fromEnv();
const orderId = process.env.MARKET_ORDER_ID!;           // item.id from createMarketOrder
const pairingToken = process.env.AGENT_PAIRING_TOKEN!;  // pairingToken from createAgentPairing

try {
  const result = await client.orchestration.executeMarketOrder(orderId, {}, pairingToken);
  if (result.execution.statusCode === 200) {
    // Native execution
    const { run, outcome } = result.execution;
  }
} catch (err) {
  if (!(err instanceof OrchestrationApiError) || err.code !== "INVALID_RESPONSE_SHAPE") throw err;
  const { item: order } = await client.orchestration.getMarketOrder(orderId);
  if (order.status !== "handoff") throw err;
  const { handoff } = order;   // { label, url, notes }
}
```

`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](/peaqos/api-reference/machine-markets-orders).

## Payment settlement

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.createPaymentIntent(
  orderId: string,
  params: CreatePaymentIntentRequest,      // { rail?, amount?, currency? }
  pairingToken: string,
): Promise<ItemResponse<MarketPayment>>

client.orchestration.getMarketPayment(
  orderId: string,
): Promise<ItemResponse<MarketPayment | null>>  // platform auth; the server answers 404 NOT_FOUND when the order has no payment, so expect OrchestrationApiError rather than a null item

client.orchestration.submitPaymentProof(
  orderId: string,
  params: SubmitPaymentProofRequest,       // EVM: transactionHash | Solana: transactionSignature + verificationMode + chain, token, payerAddress, payeeAddress, amount
  pairingToken: string,
): Promise<ItemResponse<MarketPayment>>

client.orchestration.lockEscrowPayment(
  orderId: string,
  params: LockEscrowPaymentRequest,        // { transactionHash, chain, escrowAddress } all required
  pairingToken: string,
): Promise<ItemResponse<MarketPayment>>

client.orchestration.releasePayment(
  orderId: string,
  params: ReleasePaymentRequest | undefined,  // { transactionHash?, notes? }
  pairingToken: string,
): Promise<ItemResponse<MarketPayment>>

client.orchestration.refundPayment(
  orderId: string,
  params: RefundPaymentRequest | undefined,   // { transactionHash?, reason? }
  pairingToken: string,
): Promise<ItemResponse<MarketPayment>>
```

`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:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
for await (const m of client.orchestration.listMachinesAll()) { /* … */ }
for await (const s of client.orchestration.listSkillsAll()) { /* … */ }
for await (const svc of client.orchestration.listMarketServicesAll()) { /* … */ }
for await (const o of client.orchestration.listMarketOrdersAll({ machineId: "m-1" })) { /* … */ }
for await (const p of client.orchestration.listAgentPairingsAll("m-1")) { /* … */ }
for await (const e of client.orchestration.listRuntimeEndpointsAll("m-1")) { /* … */ }
```

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`:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
let cursor: string | undefined;
do {
  const page = await client.orchestration.listMarketOrders({ machineId: "m-1", limit: 50, cursor });
  for (const order of page.items) handle(order);
  cursor = page.nextCursor;             // undefined when terminal
} while (cursor);
```

## Policies

Cross-cutting policy records above and beyond a pairing's delegation policy. Platform auth.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.listPolicies()
  : Promise<ListResponse<Policy>>

client.orchestration.createPolicy(params: CreatePolicyRequest)
  : Promise<ItemResponse<Policy>>

client.orchestration.updatePolicy(policyId: string, params: Partial<CreatePolicyRequest>)
  : Promise<ItemResponse<Policy>>
```

There is no `getPolicy` method. Read a single policy out of `listPolicies`.

## Observability

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
client.orchestration.checkHealth(): Promise<HealthResponse>        // GET /api/v1/health

client.orchestration.getReadiness(): Promise<ReadinessResponse>    // GET /api/v1/readiness

client.orchestration.listAuditEvents(options?: {
  machineId?: string;
  resourceType?: string;
  limit?: number;
}): Promise<ListResponse<AuditEvent>>
```

`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](/peaqos/api-reference/machine-markets-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`:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
class OrchestrationError extends PeaqosError {}

class OrchestrationApiError extends OrchestrationError {
  readonly code: string;        // server-provided, e.g. "NOT_FOUND"
  readonly statusCode: number;  // HTTP 4xx/5xx
  readonly details: unknown;    // server-provided detail blob
}

class OrchestrationNetworkError extends OrchestrationError {
  // .cause carries the original transport error
}

class OrchestrationConfigError extends OrchestrationError {}

class OrchestrationValidationError extends OrchestrationError {
  readonly field: string;
  readonly constraint: string;
}
```

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:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type MachineIdentityProofInput = { challengeId: string; signature: string };

type AgentPairingChallengeResponse = {
  challengeId: string;
  agentAddress: string;
  message: string;
  expiresAt: string;
  verificationMethod: "eip191";
};

// Per-adapter credentials, accepted on market search and order creation.
type ProviderCredentials = {
  walrus?: { publisherUrl?: string; aggregatorUrl?: string; publisherToken?: string };
  akash?: { consoleApiKey?: string; consoleBaseUrl?: string; restEndpoints?: string };
  worldId?: { rpId?: string; appId?: string; verifyBaseUrl?: string };
  geodnet?: { appId?: string; appKey?: string; baseUrl?: string };
  aethir?: { ak?: string; sk?: string; baseUrl?: string };
};
```

`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.

## Related

* [Machine Markets API](/peaqos/api-reference/machine-markets-overview)
* [Orchestration (Python)](/peaqos/sdk-reference/orchestration-py)
* [Scale function](/peaqos/functions/scale)
* [Machine Markets concept](/peaqos/concepts/machine-markets)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.