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

# Machine Markets: Skills, services, search

> Browse the skill registry, the partner service catalogue, and run machine-aware market search on the peaqOS Machine Markets API.

Skills are the shared schema. Services are concrete provider instances from those schemas. Search ranks services against machine context and requirements.

See the [Machine Markets overview](/peaqos/api-reference/machine-markets-overview) for base path, auth model, common envelopes, and error codes.

## Types

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type SkillSummary = {
  key: string;
  providerKey: string;
  label: string;
  description: string;
  serviceTypes: ServiceType[];
  operations: string[];
  executionMode: ExecutionMode;
  integrationStatus: IntegrationStatus;
};

type MarketService = {
  id: string;
  skillKey: string;
  providerKey: string;             // peaqOS adapter or gateway key
  companyName: string;             // underlying company (Tether, Google, Anthropic, ...)
  serviceType: ServiceType;
  name: string;
  description: string;
  operations: string[];
  pricing: {
    mode: "provider-defined" | "fixed" | "quote-required";
    amount?: number | null;
    currency?: string | null;
    rate?: string | null;          // e.g. "per_request", "per_1m_tokens"
    notes: string[];
  };
  payment: MarketOrder["payment"]; // copy of the rail recommendation
  endpoints: Array<{
    label?: string | null;
    operation?: string | null;
    url?: string | null;
    method?: string | null;        // HTTP method when applicable
    path?: string | null;
    providerName?: string | null;
    key?: string | null;
    protocols: string[];           // e.g. ["x402"], ["mpp"]
    networks: string[];            // e.g. ["base", "solana"]
  }>;
  endpoint?: {                     // legacy single-endpoint alias for endpoints[0]
    label?: string | null;
    operation?: string | null;
    url?: string | null;
    method?: string | null;
    path?: string | null;
    providerName?: string | null;
    key?: string | null;
    protocols: string[];
    networks: string[];
  } | null;
  consumption: {                   // canonical flow paths for this service
    adapterSetupPath: string;
    serviceDetailPath: string;
    marketSearchPath: string;
    orderPath: string;
    paymentIntentPath: string | null;
    paymentProofPath: string | null;
    orderExecutePath: string;
    confirmPath: string;
    directExecutePath: string | null;  // set for free read-only services
    requiredContext: string[];
    requiredRequestFields: string[];
    optionalRequestFields: string[];
    paymentFields: string[];
    instructions: string[];
  };
  executionMode: ExecutionMode;
  integrationStatus: IntegrationStatus;
  region: string;
  capabilities: string[];
  handoff?: {
    label: string;
    url: string;
    notes: string[];
  } | null;
  metadata: Record<string, unknown>;
};

type CatalogService = MarketService & {
  providerId: string;
  providerLabel: string;
  authType: "none" | "bearer" | "api-key" | "wallet" | "local";
  accessMode: "public" | "credentialed" | "partner-approved" | "whitelisted" | "local";
  distribution: "peaq-native" | "clawhub" | "openapi" | "mcp" | "docs-only";
  maturity: "reference" | "beta" | "production";
  kind: "runtime" | "reference";
  freshnessSeconds: number;
  requiresHumanEnablement: boolean;
  referenceUrl?: string;
  artifactUrl?: string;
};

type MarketQuote = {
  id: string;
  serviceId: string;
  skillKey: string;
  providerKey: string;
  executionMode: ExecutionMode;
  integrationStatus: IntegrationStatus;
  operation: string;
  score: number;
  reasons: string[];
  pricing: {
    mode: "provider-defined" | "fixed" | "quote-required";
    amount: number | null;
    currency: string | null;
    rate: string | null;
    notes: string[];
  };
  payment: {
    defaultRail: "not-required" | "x402" | "vault-stripe" | "escrow"
      | "offchain-record" | "external" | "onchain-escrow";
    supportedRails: MarketQuote["payment"]["defaultRail"][];
    required: boolean;
    provider: string | null;
    chain: string | null;
    token: string | null;
    walletAddress: string | null;
    externalUrl: string | null;
    notes: string[];
  };
  expiresAt: string;              // 15 minutes from search creation
};

type MarketSearch = {
  id: string;
  machineId: string;
  agentPairingId: string | null;
  request: Record<string, unknown>;   // original search body, provider credentials redacted
  normalizedTask: {
    serviceType: ServiceType;
    operation?: string;
    requiredCapabilities: string[];
    region?: string;
    allowExternalHandoff: boolean;
    requireNativeExecution: boolean;
  };
  status: "completed" | "no_match";
  quotes: MarketQuote[];
  createdAt: string;
};
```

## Skills

### `GET /skills`

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ListSkillsResponse = ListResponse<SkillSummary>;
```

### `GET /skills/:skillKey`

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type GetSkillResponse = ItemResponse<SkillSummary>;
```

### `GET /skills/:skillKey/manifest`

Returns the full skill manifest, including per-operation input/output contracts. Use this when an <Tooltip tip={G.sdk.def}>SDK</Tooltip> or integrator needs the schema for a skill without resolving a market service first.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type OperationFieldSpec = {
  key: string;
  type: string;
  required?: boolean;
  description: string;
  example?: unknown;
  defaultFrom?: string;       // e.g. "service.metadata.feedId"
  enum?: string[];
  fields?: OperationFieldSpec[];
};

type OperationContract = {
  operation: string;
  summary?: string;
  inputFields: OperationFieldSpec[];
  outputFields: OperationFieldSpec[];
  exampleInput?: Record<string, unknown>;
  exampleOutput?: unknown;
  notes?: string[];
};

type SkillManifest = {
  key: string;
  providerKey: string;
  label: string;
  summary: string;
  listing: {
    direction: SkillDirection;
    scope: SkillScope;
    source: SkillSource;
    listedBy: string;
    lastVerifiedAt: string | null;
  };
  distribution: SkillDistribution;
  maturity: SkillMaturity;
  inputs: OperationFieldSpec[];
  outputs: OperationFieldSpec[];
  access: {
    accessMode: SkillAccessMode;
    requiredEnv: string[];
    requiresHumanEnablement: boolean;
    notes: string[];
  };
  usage: {
    operations: string[];
    referenceUrl?: string;
    artifactUrl?: string;
    handoff?: ExternalHandoff;
  };
  operationContracts?: OperationContract[];
};

type GetSkillManifestResponse = ItemResponse<SkillManifest>;
```

`operationContracts` also surfaces on `MarketQuote.operationContract` (single, optional) and on `MarketService.operationContracts` (full list) so downstream code can build a request without a second roundtrip.

## Service catalog

### `GET /catalog`

Returns the normalised backend service catalogue used by discovery and market service listing. `companyName` is the underlying service company or organisation; `providerKey` remains the peaqOS adapter or gateway.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ListCatalogServicesQuery = {
  limit?: number;
  cursor?: string;
};

type ListCatalogServicesResponse = ListResponse<CatalogService>;
```

## Adapter setup catalog

### `GET /market/adapter-credential-stack`

Public endpoint that feeds the frontend "adapter setup" cards (the rich provider tiles on robotic.sh and the peaq app's Services page). Data is backend-owned and repo-backed; the public API does not write. Adding or updating an adapter requires a PR to `peaqos-orchestration` that adds a registry entry and passes the metadata completeness tests; the PR template lives at `.github/PULL_REQUEST_TEMPLATE/adapter-setup-catalog.md`.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ListAdapterServiceListingsQuery = {
  providerKey?: string;
  skillKey?: string;
  serviceType?: ServiceType;
  limit?: number;
  cursor?: string;
};

type ListAdapterServiceListingsResponse = ListResponse<AdapterServiceListing>;

type AdapterServiceListing = {
  providerKey: string;
  label: string;
  displayName: string;
  companyName: string;             // underlying company or organisation
  description: string;
  category:
    | "inference" | "vision" | "speech" | "navigation"
    | "positioning" | "translation" | "web" | "onchain"
    | "compute" | "storage";
  chains: Array<"base" | "solana" | "peaq" | "sui">;
  price: string;
  robotTypes: Array<"drones" | "amrs" | "humanoids" | "evs" | "arms" | "sensors">;
  serviceTypes: ServiceType[];
  skillKeys: string[];
  setupUrl: string;
  referenceUrl: string;
  serviceCatalogPath: string;      // fetch endpoint-level services for this adapter
  paymentRails: string[];
  authModes: string[];             // e.g. ["bearer", "api-key", "wallet"]
  setupComplexity: "low" | "medium" | "high";
  displayOrder: number;
  requiresCredentials: boolean;
  requiredFields: string[];
  optionalFields: string[];
  nativeExecutionAvailableWithCredentials: boolean;
  nativeExecutionNote: string;
  operatorAction: string;
  agentInstructions: string[];
};
```

Launch adapter registry: `qvac` (inference, Tether strategic), `pay-sh` (web), `agentic-market` (x402 services). Each entry carries a `setupUrl` pointing at the central robotic.sh catalog, a provider-specific `referenceUrl`, and a `serviceCatalogPath` you call to fetch the endpoint-level services that belong to the adapter. Those service records include callable endpoint URLs, pricing, <Tooltip tip={G.paymentRail.def}>payment rails</Tooltip>, and consumption instructions.

Frontend rendering uses `category`, `robotTypes`, `chains`, and `setupComplexity` for filter chips; `displayOrder` controls the card order on the page. `requiresCredentials` plus `requiredFields` / `optionalFields` drive the credential-entry modal.

## Market services

### `GET /market/services`

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ListMarketServicesQuery = {
  serviceType?: ServiceType;
  executionMode?: ExecutionMode;
  providerKey?: string;
  machineId?: string;     // include to filter against machine context
};

type ListMarketServicesResponse = ListResponse<MarketService>;
```

### `GET /market/services/:serviceId`

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type GetMarketServiceQuery = {
  machineId?: string;
};

type GetMarketServiceResponse = ItemResponse<MarketService>;
```

### `POST /market/services/:serviceId/execute`

Directly executes a native, read-only service operation without creating a market order. Use this for free lookup or read operations. Paid, external-handoff, and state-changing operations must still flow through `POST /market/orders`.

Requires an active peaqOS machine, an active Machine Agent pairing, and pairing session token auth when enabled.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type ExecuteMarketServiceRequest = {
  machineId: string;
  agentPairingId: string;
  operation: string;
  input?: Record<string, unknown>;
  budget?: {
    amount?: number;
    max?: number;
    currency?: string;
  };
  providerCredentials?: ProviderCredentials;
};

type ExecuteMarketServiceResponse = {
  service: MarketService & {
    operation: string;
    payment: MarketOrder["payment"];
  };
  execution: {
    task: Record<string, unknown>;
    route: Record<string, unknown>;
    outcome: Record<string, unknown>;
    run: Record<string, unknown>;
  };
};
```

## Market search

### `POST /market/search`

Submits a normalised search and returns a ranked `MarketSearch` with quotes.

Required preconditions:

* the machine is `active`
* its `identityRef` is verified with an identity ownership proof
* there is an active Machine Agent pairing for the machine
* when `PEAQOS_REQUIRE_AGENT_PAIRING_AUTH=true`, the `x-agent-pairing-token` header is present

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type SearchMarketRequest = {
  machineId: string;
  agentPairingId?: string;             // required if the machine has more than one active pairing
  serviceType: ServiceType;
  operation?: string;
  requiredCapabilities?: string[];
  region?: string;
  maxResults?: number;                 // integer 1-25, default 5
  allowExternalHandoff?: boolean;
  requireNativeExecution?: boolean;
  budget?: {
    amount?: number;                   // max acceptable cost; alias of `max`
    max?: number;                      // alias of `amount`
    currency?: string;                 // defaults to "USD"
  };
  providerCredentials?: ProviderCredentials; // redacted before persistence
};

type SearchMarketResponse = ItemResponse<MarketSearch>;
```

Errors: `MACHINE_NOT_ACTIVE`, `MACHINE_IDENTITY_PROOF_REQUIRED`, `AGENT_PAIRING_REQUIRED`, `AGENT_PAIRING_INACTIVE`, `AGENT_AUTH_REQUIRED`, `AGENT_AUTH_INVALID`, `AGENT_AUTH_EXPIRED`, `AGENT_POLICY_DENIED`, `VALIDATION_ERROR`.

### `GET /market/searches/:searchId`

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
type GetMarketSearchResponse = ItemResponse<MarketSearch>;
```

## Related

* [Machine Markets overview](/peaqos/api-reference/machine-markets-overview)
* [Machine Markets: Machines & identity](/peaqos/api-reference/machine-markets-machines)
* [Machine Markets: Pairings](/peaqos/api-reference/machine-markets-pairings)
* [Machine Markets concept](/peaqos/concepts/machine-markets)
* [Scale function](/peaqos/functions/scale)
