Skip to main content

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.

A Machine Agent buys a service through an order. The orchestrator owns the full lifecycle: order create, payment intent, proof or escrow lock, execute, confirm, dispute, release, refund. Server-side enforcement covers identity proofs, agent pairing, delegation policy, per-transaction and daily spend limits, quote freshness, and rail compatibility. See the Machine Markets overview for base path, auth model, and common envelopes.

Order state machine

created -> payment_pending -> ready -> executing -> delivered -> confirmed
                                                              \-> handoff
                                                              \-> disputed
                                                              \-> failed
                                                              \-> cancelled

Payment state machine

intent_created -> held -> release_pending -> released
not_required                              \-> refunded
                                          \-> frozen   (on dispute)

Types

type MarketOrderStatus =
  | "created" | "payment_pending" | "ready" | "executing"
  | "delivered" | "confirmed" | "disputed" | "cancelled"
  | "failed" | "handoff";

type MarketPaymentStatus =
  | "not_required" | "intent_created" | "held" | "release_pending"
  | "released" | "frozen" | "refunded";

type MarketPaymentRailType =
  | "not-required" | "wallet" | "x402" | "xvv42"
  | "vault-stripe" | "wdk-usdt-transfer" | "escrow"
  | "offchain-record" | "external" | "onchain-escrow";

type MarketOrderRecord = {
  id: string;
  machineId: string;
  agentPairingId: string;
  searchId: string | null;
  quoteId: string | null;
  serviceId: string;
  skillKey: string;
  providerKey: string;
  serviceType: ServiceType;
  operation: string;
  executionMode: ExecutionMode;
  integrationStatus: IntegrationStatus;
  status: MarketOrderStatus;
  input: Record<string, unknown>;
  budget?: { amount?: number | null; currency?: string | null } | null;
  payment: MarketPaymentRailRecommendation;
  serviceSnapshot: Record<string, unknown>;
  taskId: string | null;
  routeId: string | null;
  runId: string | null;
  outcomeId: string | null;
  handoff: ExternalHandoff | null;
  errorMessage: string | null;
  createdAt: string;
  updatedAt: string;
};

type MarketPaymentRailRecommendation = {
  defaultRail: MarketPaymentRailType;
  supportedRails: MarketPaymentRailType[];
  required: boolean;
  provider?: string | null;
  chain?: string | null;
  token?: string | null;
  walletAddress?: string | null;
  externalUrl?: string | null;
  notes: string[];
};

type MarketPaymentRecord = {
  id: string;
  orderId: string;
  machineId: string;
  status: MarketPaymentStatus;
  rail: {
    type: MarketPaymentRailType;
    chain?: string | null;
    token?: string | null;
    escrowAddress?: string | null;
    externalUrl?: string | null;
    provider?: string | null;
    accountId?: string | null;
    walletAddress?: string | null;
    payerAddress?: string | null;
    payeeAddress?: string | null;
    tokenAddress?: string | null;
    transactionHash?: string | null;
    paymentIntentId?: string | null;
    metadata?: Record<string, unknown>;
  };
  amount?: number | null;
  currency?: string | null;
  proof?: {
    transactionHash: string;
    verificationMode: "recorded" | "rpc";
    status: "recorded" | "verified";
    chain?: string | null;
    token?: string | null;
    tokenAddress?: string | null;
    payerAddress?: string | null;
    payeeAddress?: string | null;
    amount?: string | null;
    rawAmount?: string | null;
    blockNumber?: number | null;
    verifiedAt: string;
    metadata?: Record<string, unknown>;
  } | null;
  notes: string[];
  createdAt: string;
  updatedAt: string;
};

type ExternalHandoff = {
  label: string;
  url: string;
  notes: string[];
};

type MarketDisputeRecord = {
  id: string;
  orderId: string;
  machineId: string;
  status: "open" | "resolved";
  reason: string;
  evidence: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
};

Orders

GET /market/orders?machineId={id}

Lists orders for a machine.
type ListMarketOrdersQuery = { machineId: string };
type ListMarketOrdersResponse = ListResponse<MarketOrderRecord>;
Errors: VALIDATION_ERROR, NOT_FOUND, MACHINE_NOT_ACTIVE, MACHINE_NOT_ACTIVATED.

POST /market/orders

Locks a service from the catalogue into an order. Status starts at created. The recommended payment rail is copied from the service into order.payment.
type CreateOrderRequest = {
  machineId: string;
  agentPairingId: string;
  serviceId: string;
  searchId?: string;        // required when PEAQOS_REQUIRE_MARKET_QUOTES=true
  quoteId?: string;         // required when PEAQOS_REQUIRE_MARKET_QUOTES=true
  operation?: string;
  input?: Record<string, unknown>;
  budget?: { amount?: number; max?: number; currency?: string };
  operatorCredentials?: {
    providers?: Record<string, { env?: Record<string, string> } & Record<string, string>>;
  };
};

type CreateOrderResponse = ItemResponse<MarketOrderRecord>;
Errors: VALIDATION_ERROR, QUOTE_EXPIRED, AGENT_PAIRING_REQUIRED, AGENT_PAIRING_INACTIVE, AGENT_POLICY_DENIED, AGENT_SPEND_LIMIT_EXCEEDED, AGENT_DAILY_LIMIT_EXCEEDED, MACHINE_NOT_ACTIVE, MACHINE_NOT_ACTIVATED, NOT_FOUND.

GET /market/orders/:orderId

type GetMarketOrderResponse = ItemResponse<MarketOrderRecord>;

Payment

POST /market/orders/:orderId/payment-intent

Creates or returns the payment record. Idempotent: returns the existing payment if one already exists. For not-required rails the order moves straight to ready.
type CreatePaymentIntentRequest = {
  amount?: number;
  currency?: string;
  rail?: {
    type?: MarketPaymentRailType;
    chain?: string;
    token?: string;
    tokenAddress?: string;
    tokenMint?: string;        // alias for tokenAddress on Solana
    escrowAddress?: string;
    externalUrl?: string;
    provider?: string;
    accountId?: string;
    walletAddress?: string;
    payerAddress?: string;
    payeeAddress?: string;
    transactionHash?: string;
    paymentIntentId?: string;
    metadata?: Record<string, unknown>;
  };
  payerAddress?: string;
  payeeAddress?: string;
  tokenAddress?: string;
  tokenMint?: string;
  transactionHash?: string;
  txHash?: string;
};

type CreatePaymentIntentResponse = ItemResponse<MarketPaymentRecord>;
Errors: NOT_FOUND, VALIDATION_ERROR (unsupported rail, invalid address, rail not in service supportedRails when PEAQOS_ENFORCE_SERVICE_PAYMENT_RAILS=true).

POST /market/orders/:orderId/payment-proof

Records a payment proof. recorded mode stores operator attestation. rpc mode queries an EVM RPC for the transaction receipt and validates the ERC-20 Transfer log against expected token, sender, recipient, and raw amount. Solana proofs are always recorded.
type RecordPaymentProofRequest = {
  transactionHash: string;  // EVM 0x… 64 hex, or Solana base58 64–100. Aliases: txHash, transactionSignature, signature.
  chain?: string;            // default "peaq"
  token?: string;            // default "USDT"
  payerAddress?: string;
  payeeAddress?: string;
  tokenAddress?: string;     // aliases: tokenMint, usdtContract; falls back to PEAQOS_USDT_CONTRACT
  amount?: string;
  rawAmount?: string;        // integer in token base units
  tokenDecimals?: number;    // 0..36, default 6
  verificationMode?: "recorded" | "rpc";  // default rpc when RPC URL set
  rpcUrl?: string;
  metadata?: Record<string, unknown>;
};

type RecordPaymentProofResponse = ItemResponse<MarketPaymentRecord>;
Errors: NOT_FOUND, ORDER_CLOSED, VALIDATION_ERROR, PAYMENT_RPC_REQUIRED (rpc mode with no RPC URL), PAYMENT_RPC_ERROR (502), PAYMENT_NOT_MINED (409, receipt null), PAYMENT_TX_FAILED (402, receipt status not 0x1), PAYMENT_TRANSFER_NOT_FOUND (400, no matching Transfer log). On successful verification the rail type upgrades from wallet to wdk-usdt-transfer. Payment status moves to held; order moves created/payment_pendingready.

GET /market/orders/:orderId/payment

type GetMarketPaymentResponse = ItemResponse<MarketPaymentRecord>;

POST /market/orders/:orderId/payment/escrow-lock

Records an on-chain escrow lock. Payment → held. Order → ready. Idempotent for held.
type EscrowLockRequest = {
  transactionHash: string;
  chain: string;
  escrowAddress: string;
};

type EscrowLockResponse = ItemResponse<MarketPaymentRecord>;
Errors: NOT_FOUND, ORDER_CLOSED, VALIDATION_ERROR.

POST /market/orders/:orderId/payment/release

Releases held funds after confirm. Payment must be release_pending, order must be confirmed. Status → released.
type ReleasePaymentRequest = {
  transactionHash?: string;
  notes?: string;
};

type ReleasePaymentResponse = ItemResponse<MarketPaymentRecord>;
Errors: NOT_FOUND, ORDER_CLOSED, ORDER_NOT_DELIVERED. Idempotent for released and not_required.

POST /market/orders/:orderId/payment/refund

Refunds payment. Status → refunded. Open orders move to cancelled.
type RefundPaymentRequest = {
  transactionHash?: string;
  reason?: string;
};

type RefundPaymentResponse = ItemResponse<MarketPaymentRecord>;
Errors: NOT_FOUND, ORDER_CLOSED. Idempotent for refunded and not_required.

Execute, confirm, dispute

POST /market/orders/:orderId/execute

Materialises the order as a task plus route, runs the skill runtime, writes a Run and an Outcome. Order status moves executingdelivered (outcome completed) / handoff (outcome external) / failed. The HTTP status code is propagated from the inner execution result.
type ExecuteOrderRequest = Record<string, unknown> & {
  operatorCredentials?: {
    providers?: Record<string, { env?: Record<string, string> } & Record<string, string>>;
  };
};

type ExecuteOrderResponse = {
  order: MarketOrderRecord;
  execution: {
    statusCode: number;
    outcome: OutcomeRecord;
    run: RunRecord;
    resolution: TaskResolution;
  };
};
Errors: ORDER_CLOSED (order in confirmed / disputed / cancelled), PAYMENT_REQUIRED (when PEAQOS_REQUIRE_PAYMENT_BEFORE_EXECUTE=true, the production default, and payment is not in not_required / held / release_pending / released — except intent_created is allowed for external / vault-stripe rails). All downstream skill-runtime errors are surfaced as well. x402-rail services (Agentic Market, most pay.sh) execute through the paidHttp adapter. The execute call replays the original 402-challenged request with the operator-supplied payment headers (x-payment, payment-signature, authorization, sign-in-with-x). The payment intent response now preserves the full x402 accepts[] entries including extra (EIP-712 signing metadata: { name: "USD Coin", version: "2" }-style) and outputSchema. Operators that build their own paid-HTTP adapters should pass headers under operatorCredentials.providers[providerKey]; raw headers are stripped from request bodies before forwarding and never persisted.

POST /market/orders/:orderId/confirm

Buyer confirms delivery. Order delivered / handoffconfirmed. Payment heldrelease_pending.
type ConfirmOrderResponse = {
  order: MarketOrderRecord;
  payment: MarketPaymentRecord | null;
};
Errors: ORDER_NOT_DELIVERED.

POST /market/orders/:orderId/dispute

Opens a dispute record. Order → disputed. Payment → frozen. Returns 201.
type DisputeOrderRequest = {
  reason: string;
  evidence?: Record<string, unknown>;
};

type DisputeOrderResponse = {
  order: MarketOrderRecord;
  payment: MarketPaymentRecord | null;
  dispute: MarketDisputeRecord;
};
Errors: VALIDATION_ERROR (missing reason).