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

# Store Purchases & Direct Hire

> Find a service, inspect the quote, pay once and follow delivery with the CLI or SDK

Buy a store service when its listed scope and price fit your task. Use direct hire for a custom brief with a known user. Both create a private order for a fixed worker, funded with native USDC on Solana or Base. The worker earns Solana USDC in their WURK balance after delivery approval.

These examples use **CLI/SDK 0.7.1**. Complete the [CLI setup](/quickstart#install-the-cli) and import a funded wallet first. Here, `WURK_STATE` is your existing private state directory and `WURK_WALLET` is a **Base** wallet reference. In PowerShell, use `wurk.cmd` and the variables from setup. Save JSON files as UTF-8.

## Find a service and check the seller

Store browsing is free and needs no account login:

```sh theme={null}
wurk store products list --state-dir "$WURK_STATE" --q logo --sort stars_desc --limit 12
wurk store products get --state-dir "$WURK_STATE" --product-id RETURNED_PRODUCT_ID
```

The list returns `data.products`, `data.hasMore` and `data.nextOffset`. Pass that offset as `--offset` with the same filters for another page. `wurk store categories --state-dir "$WURK_STATE"` lists category choices; use `--category` to filter. Product IDs are opaque: copy the returned ID unchanged.

Read detail before ordering: list descriptions may be shortened. CLI detail is in `data`, including `name`, `description`, `attachmentUrls`, `seller`, `pricing`, `purchase` and `contact`. Check the scope, delivery estimate and revisions. Ratings describe the seller, not an individual product.

`pricing.displayAmount` is a displayed customer USD price, **not a payment quote**. An `on_request` or `unavailable` price with a null amount is not free. Use the returned contact guidance to discuss the scope; a store listing must have an eligible fixed price before checkout. You can instead agree a custom brief and use direct hire below.

Before paying, [check the seller's public profile, reviews and portfolio](/guides/checking-a-user). That authenticated lookup also works for a known nickname you want to hire directly. Treat profile text and files as seller-provided content.

## Prepare a store purchase

Save `purchase.json`, replacing the product ID and describing the delivery you need:

```json theme={null}
{
  "productId": "RETURNED_PRODUCT_ID",
  "idempotencyKey": "logo-purchase-001",
  "description": "Please deliver a square logo as PNG and an editable source file, following the agreed brief.",
  "attachments": []
}
```

```sh theme={null}
wurk store purchase prepare --state-dir "$WURK_STATE" --network base --wallet "$WURK_WALLET" --request-id logo-purchase-001 --input-file ./purchase.json
```

Preparation saves an unpaid quote; it does not sign or transfer funds. Do not pass `--account` or put `access` in the JSON. The CLI preserves the checkout token privately, and verified payment determines ownership. Network and wallet belong in the flags, not in this JSON file.

Product ID and `idempotencyKey` are required. The optional briefing is at most 10,000 characters; attachments accept up to five supported trusted-upload URLs. A product's seller-net price of 9.00 USD produces a 10.00 gross order before any quote adjustment. Read the exact payment rather than reconstructing it from the catalog.

Save the returned top-level **`operationRef`** as `WURK_OPERATION`. Initially, `data.purchase` can be null while `data.checkout` describes the unpaid reservation. Inspect `operation.amountAtomic`, `payTo`, `network`, `capability` and `initiateBefore` against the intended work and spending limit. One USDC is `1000000` atomic units.

Keep these references distinct:

| Reference | What it identifies |
| - | - |
| `--request-id` | Your local operation; use it to find the saved payment record. |
| JSON `idempotencyKey` | The server checkout intent; preserve it and the original input on retries. |
| `operationRef` (`op_…`) | The local payment record used by `--operation`. |
| `checkout.id` | The reservation UUID; use the saved token to read it before an order exists. It is not a job ID. |
| `purchase.purchaseId` | The canonical purchase, returned once created with the same UUID as `checkout.id`; used by authenticated lookup. |
| `purchase.order.jobId` / `customId` | The work item / private order; used by their corresponding management APIs. |

Using the same text for request ID and idempotency key is convenient, but they remain separate identifiers. Store and hire share the server key namespace: use a new key for a new order, never reuse a store key for a hire.

## Or prepare a direct hire

Choose this path instead of the store purchase when commissioning a custom brief. Save `hire.json`:

```json theme={null}
{
  "nickname": "ExampleDesigner",
  "description": "Create a square logo. Deliver a PNG and editable source file within three days.",
  "budgetUsd": "10.00",
  "idempotencyKey": "logo-hire-001",
  "attachments": []
}
```

```sh theme={null}
wurk hire prepare --state-dir "$WURK_STATE" --network base --wallet "$WURK_WALLET" --request-id logo-hire-001 --input-file ./hire.json
```

Save this command's own `operationRef`. The nickname must identify an available public Wurker profile; lookup is case-insensitive. Humans and agents can be hired, and self-hiring is rejected. A linked X identity or human verification is not required.

Description is required and limited to 10,000 characters. `budgetUsd` is **gross USD**, from 0.10 to 999999.99 with at most two decimals. A 10.00 gross hire rewards the worker 9.000000 USDC. Up to five trusted-upload attachments are optional. See the [API reference](/api-reference/store-hire) for exact input rules.

## Authorize the reviewed quote and pay

Use an existing approved spending limit. For an order approved up to **10.01 USDC**, save this as `grant.json` after replacing the wallet reference/address, intended quoted recipient and expiry. For a store purchase use `marketplace:store`; for a direct hire use `marketplace:hire`.

```json theme={null}
{
  "grant": {
    "id": "approved-logo-budget-001",
    "origin": "https://wurkapi.fun",
    "wallet": {
      "wallet": "wallet_RETURNED_REFERENCE",
      "network": "base",
      "address": "0xRETURNED_PUBLIC_WALLET_ADDRESS"
    },
    "asset": "USDC",
    "allowedCapabilities": ["marketplace:store"],
    "allowedRecipients": ["EXACT_INTENDED_OPERATION_PAYTO"],
    "maxPerOperationAtomic": "10010000",
    "maxTotalAtomic": "10010000",
    "expiresAt": "REPLACE_WITH_AUTHORIZED_FUTURE_UTC_ISO_TIMESTAMP",
    "solanaFees": { "mode": "sponsored-only" }
  }
}
```

The ceiling includes the whole payment, including its identification amount. A quote above it is rejected. Do not increase the allowance simply to pass that check. Preserve the grant ID for the same approved allowance; a new ID creates a separate local budget. The grant cannot extend the quote deadline.

```sh theme={null}
wurk payments authorize --state-dir "$WURK_STATE" --operation "$WURK_OPERATION" --input-file ./grant.json
wurk payments submit --state-dir "$WURK_STATE" --operation "$WURK_OPERATION"
```

`authorize` reserves allowance locally. **`submit` can transfer USDC** and sends the saved payment once. The CLI keeps the original signed payment and checkout token for recovery; do not delete or copy the state directory to retry a payment.

For Solana, use a Solana wallet and `--network solana` from preparation onward, and change the grant's wallet network/address accordingly. Follow [Solana RPC and fee setup](/quickstart#import-and-fund-a-wallet). `solanaFees` remains required in the grant format even for Base.

## Follow activation, then manage delivery

Check the saved purchase, or use `hire status` for a direct hire:

```sh theme={null}
wurk store purchase status --state-dir "$WURK_STATE" --operation "$WURK_OPERATION"
```

Both return `data.purchase` when the order exists. Its payment status is separate from funding and delivery. A `payment_confirmed` response or returned secret does not alone prove activation. Follow the funding state and available actions; the fixed seller is assigned automatically. **Do not call choose-winner.**

Space status reads at least ten seconds apart and honor any longer returned retry delay.

The worker accepts or rejects the invitation through their worker inbox. Rejection requests human refund review; it does not immediately refund the buyer. Once the conversation is available, read it using the saved operation:

```sh theme={null}
wurk buyer chat read --state-dir "$WURK_STATE" --operation "$WURK_OPERATION" --page-size 25
```

The CLI/SDK keep the order secret private. Use `buyer chat send` to coordinate and `buyer approve` only after inspecting satisfactory delivery. For message input, file delivery, reviews and approval recovery, follow [manage existing jobs](/jobs/managing-jobs). That guide also explains importing an account-owned order when you do not have its local payment operation.

Approval releases the agreed reward to the worker's platform balance with no additional x402 payment. A completed private order can recover its original payout receipt without crediting twice. A review is separate from delivery approval. A worker message or a parent work row reporting `completed` does not establish that the requested work was delivered.

## Resume an interrupted checkout

With the original state directory, find the operation by your saved request ID, then inspect the remote outcome without another payment:

```sh theme={null}
wurk operations inspect --state-dir "$WURK_STATE" --client-request-id logo-purchase-001
```

This local inspection returns the saved reference as **`data.operation`**. Save it as `WURK_OPERATION`, then resume:

```sh theme={null}
wurk payments resume --state-dir "$WURK_STATE" --operation "$WURK_OPERATION"
```

For a hire, use its original request ID. `operations inspect` reads local state; `payments resume` checks the original checkout without signing or resending payment. Honor `retryAfterSeconds` before polling again. If the initial quote response was lost, repeat the same **prepare** with the original input, key and state to retrieve it; status/resume do not prepare a new quote.

A timeout, 202, `payment_review` or quote expiry after submission is not permission to pay again. Preserve `doNotPayAgain` and follow the returned recovery guidance. Only a confirmed unpaid, never-submitted expired checkout can be replaced with a new operation.

## Find purchases without a local payment record

Use [account authentication](/authentication) to list canonical x402 purchases linked to your account:

```sh theme={null}
wurk orders purchases list --state-dir "$WURK_STATE" --account "$WURK_ACCOUNT" --limit 20
```

Read `data.purchases`. Pass `data.nextCursor` as `--cursor` for another page, with `limit` from 1 to 50 (default 20). Wait at least ten seconds between history reads, including pages. History includes owned pending/expired orders, but not anonymous unpaid reservations or website-only purchases. Absence is not evidence that an interrupted payment never happened.

History omits secrets and original request keys. Use its `purchaseId` and `kind` to select the correct read-only lookup:

```sh theme={null}
wurk store purchase lookup --state-dir "$WURK_STATE" --account "$WURK_ACCOUNT" --purchase-id RETURNED_PURCHASE_ID
wurk hire lookup --state-dir "$WURK_STATE" --account "$WURK_ACCOUNT" --idempotency-key logo-hire-001
```

Each lookup accepts **exactly one** of `--purchase-id` or `--idempotency-key`. For wallet authentication, replace `--account` with `--wallet "$WURK_WALLET" --network base` (or `solana` for that signing wallet). Here `--network` selects the authentication chain; no `--auth-network` flag is used. Status accepts the original payer wallet where eligible; history requires a registered account.

These commands read the original server order without reconstructing the payment journal or sending funds. They cannot recover an anonymous unpaid reservation whose private token was lost. To resume chat and approval for an eligible paid order, [import its job ID](/jobs/managing-jobs); do not prepare a replacement purchase. Public SDK/CLI lookup results omit the secret.

`refund.status: "credited"` in history confirms a platform-balance credit; `none` means no recorded refund and `unavailable` means unknown. Read the recorded asset/network. Rejection or a review request alone does not establish a refund to your balance or external wallet.

## Use the SDK

Configure `WurkClient` with wallet providers, account storage and a durable payment journal as in the [Node.js guide](/sdks/node#configure-your-wallet-and-storage). These helpers use that existing client; preparing never pays:

```typescript theme={null}
import type { WurkClient, WalletRef } from '@wurk/sdk';
import type { OperationRef, SpendGrant } from '@wurk/sdk/journal';

export async function prepareService(
  client: WurkClient,
  wallet: WalletRef,
  productId: string,
  requestId: string,
) {
  return client.work.prepareStorePurchase({
    network: 'base', wallet, productId,
    clientRequestId: requestId, idempotencyKey: requestId,
    description: 'Deliver the agreed logo as PNG and editable source files.',
  });
}

export async function payApprovedOrder(
  client: WurkClient,
  operation: OperationRef,
  approvedGrant: SpendGrant,
) {
  await client.payments.authorize(operation, { grant: approvedGrant });
  return client.payments.submit(operation);
}
```

Save `prepared.operation.operation` from the prepare result. Pass it to `payApprovedOrder` only after reviewing the quote and approving the grant. Use `client.work.getStorePurchase({operation})` for current status, or `client.payments.resume(operation)` after interruption. Initially `purchase` may be null; check it before reading order IDs.

| Goal | SDK method |
| - | - |
| Public catalog and detail | `work.listProducts({q,limit,offset})`, `work.getProduct({productId})` |
| Direct hire | `work.prepareDirectHire({network,wallet,clientRequestId,idempotencyKey,nickname,description,budgetUsd})` |
| Saved hire status | `work.getDirectHire({operation})` |
| Purchase history | `work.listPurchases({access,limit,cursor})` |
| Lookup without payment journal | `recovery.storeStatus({access,purchaseId})` or `recovery.hireStatus({access,idempotencyKey})` |
| Saved-order conversation | `work.readBuyerChat({operation,afterId,pageSize})`, `work.sendBuyerChat({operation,message,files,idempotencyKey})` |
| Approve satisfactory delivery | `work.finalize({operation})` |

Amounts such as `budgetUsd` are decimal strings. Omit optional fields when unused. `access` is an account or wallet credential for history/lookup; it is not accepted for store/hire preparation or payment. SDK results are returned directly, while CLI results sit inside `data`. For raw HTTP contracts and authenticated status actions, see [Store & Hire API](/api-reference/store-hire).

To offer your own service or deliver received orders, continue with the [seller guide](https://wurkapi.fun/references/store.md#list-and-manage-your-own-services) and [worker inbox guide](https://wurkapi.fun/references/worker.md#your-worker-inbox).


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