---
name: apinow
version: 1.6.0
description: Discover APIs, fetch endpoint details/examples, execute paid calls, and run multi-step workflows on APINow with x402.
homepage: https://www.apinow.fun
metadata: {"apinow":{"category":"api-marketplace","api_base":"https://www.apinow.fun/api","api_version":"v1","payment_protocol":"x402","chain":"base","required_env":"APINOW_WALLET_PKEY"}}
---

# APINow Agent Skill

Use this skill when the user asks to find APIs, inspect endpoint schemas/examples, pay for API calls, run multi-step workflows, or run with strict API allowlists and spend limits.

## Required Environment

- Required for paid x402 calls: `APINOW_WALLET_PKEY`
- Optional paid fallback: `x-api-key` header with a funded APINow key
- Optional SIWA/CDP/managed signer paths:
  - Privy: `PRIVY_APP_ID`, `PRIVY_APP_SECRET`, `PRIVY_WALLET_ID`
  - Bankr/CDP-style agent wallet: `BANKR_API_KEY`
  - Local private-key signer: `APINOW_WALLET_PKEY`
- Frontend/browser path: use the user's wallet signer with `@x402/fetch` + `@x402/evm`; do not expose `APINOW_WALLET_PKEY` client-side

If a paid call is requested and no valid payment auth is available, stop and ask the user to provide credentials.

## Auth (for write/mutating calls)

Paid `call`/`run` routes use x402 (payment = identity). **Everything else that writes** — creating or updating endpoints, workflows, workflow versions, or factory endpoints — requires a **signed wallet Authorization header** to prevent spoofing.

Send on every write request:

```
Authorization: Bearer <message>||<signature>||<address>
x-wallet-address: <address>     (legacy fallback; will be removed)
```

Where `<message>` is plain text (signed via personal_sign / EIP-191):

```
APINow auth
address: 0xYourWallet
issuedAt: 2026-04-20T18:15:22.481Z
nonce: <random>
```

Server rules:
- Signature must recover to `<address>` via `ethers.recoverAddress(hashMessage(message), signature)`.
- `issuedAt` must be within 10 minutes of server time (`APINOW_AUTH_SKEW_MS`).
- Strict mode (`APINOW_AUTH_STRICT=1`) rejects any request missing a valid Authorization header.

### Signing with a private key (AI agent path)

```javascript
import { privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount(process.env.APINOW_WALLET_PKEY);

async function signAuthHeader() {
  const issuedAt = new Date().toISOString();
  const nonce = crypto.randomUUID();
  const message = `APINow auth\naddress: ${account.address}\nissuedAt: ${issuedAt}\nnonce: ${nonce}`;
  const signature = await account.signMessage({ message });
  return `Bearer ${message}||${signature}||${account.address}`;
}

const res = await fetch('https://www.apinow.fun/api/workflows', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: await signAuthHeader(),
    'x-wallet-address': account.address,
  },
  body: JSON.stringify({ name: 'My workflow', graph: {...}, totalPrice: '0.10' }),
});
```

### Signing with `apinow-sdk`

The SDK signs automatically on every write. Two config shapes:

```javascript
// Server / agent — raw private key (enables paid calls too)
import { createClient } from 'apinow-sdk';
const apinow = createClient({ privateKey: process.env.APINOW_WALLET_PKEY });

// `createWorkflow`, `updateWorkflow`, `createWorkflowVersion`,
// `setDefaultWorkflowVersion`, `deleteWorkflow*`, `createEndpoint`,
// `updateEndpoint`, `deleteEndpoint`, `factoryCreate`, `factoryMarkup`,
// `factoryTestCall`, `factoryGenerate` → all authenticated automatically.
const wf = await apinow.createWorkflow({ name: 'My workflow', graph: {...}, totalPrice: '0.10' });

// Need a signed header for a custom call:
const headers = await apinow.signAuthHeader();
```

```typescript
// Browser / connected wallet — plug in any EIP-191 signer
import { createClient } from 'apinow-sdk';
import { useAccount, useWalletClient } from 'wagmi';

const { address } = useAccount();
const { data: walletClient } = useWalletClient();

const apinow = createClient({
  address,
  signer: (msg) => walletClient.signMessage({ message: msg }),
});

// Writes work the same; paid calls need a paidFetch from useX402Fetch() (above).
await apinow.updateWorkflow(id, { executionMode: 'balanced' });
```

Also works with ethers BrowserProvider:

```javascript
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const apinow = createClient({
  address: await signer.getAddress(),
  signer: (msg) => signer.signMessage(msg),
});
```

### Signing with cURL (ad-hoc)

```bash
ADDR=0xYourWallet
PK=$APINOW_WALLET_PKEY
MSG=$(printf 'APINow auth\naddress: %s\nissuedAt: %s\nnonce: %s' "$ADDR" "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" "$RANDOM")
SIG=$(cast wallet sign --private-key "$PK" "$MSG")

curl -X POST https://www.apinow.fun/api/workflows \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ${MSG}||${SIG}||${ADDR}" \
  -H "x-wallet-address: ${ADDR}" \
  -d '{"name":"My workflow","prompt":"summarize a tweet and score virality"}'
```

### Auth rules summary

- **Read** routes (GET search, details, lists, workflow details, versions) → **no auth**.
- **Write** routes (create/update/delete of endpoints, workflows, versions, factory) → **signed `Authorization` required** (x-wallet-address alone is spoofable and will be rejected once `APINOW_AUTH_STRICT=1`).
- **Paid invocation** (`/api/endpoints/{ns}/{ep}`, `/api/workflows/{id}/run`) → x402 payment header (no separate auth needed).

## Capabilities

1) Discover APIs
- Semantic search: `POST /api/endpoints/semantic-search`
- Text search/listing: `GET /api/endpoints`
- Catalog listing: `GET /api/catalog`
- Endpoint details/schema: `GET /api/endpoints/{namespace}/{endpoint}/details`
- LLM-oriented examples: `GET /api/endpoints/{namespace}/{endpoint}/vibecode`
- Optional allowlist filters for both search APIs:
  - `allowed_lists`: list slugs to restrict search scope
  - `allowed_endpoints`: explicit endpoint keys (`namespace/endpoint`)

2) Execute paid API calls
- Endpoint invocation: `POST /api/endpoints/{namespace}/{endpoint}`
- Uses x402 (`402 -> sign -> retry`) with `APINOW_WALLET_PKEY`, or API key path.

3) Query lists and enforce list-only mode
- Browse lists: `GET /api/lists`
- Load list details/endpoints and treat as hard allowlist when the user requests list-restricted execution.
- Reject endpoint calls outside the active allowlist.

4) Workflows
- List workflows: `GET /api/workflows`
- Get workflow details: `GET /api/workflows/{workflowId}` (returns `currentVersion`, `currentVersionId`, `creatorWallet`, `nameUpdatedAt`, `descriptionUpdatedAt`)
- Run a workflow: `POST /api/workflows/{workflowId}/run`
- Workflows chain multiple x402 endpoints into a DAG pipeline with a single payment + automatic splitting.
- Each workflow has: a `creatorWallet` (like an endpoint's `walletAddress`), nodes (endpoint references with dependency graph), totalPrice (USDC), and splits (payment distribution to endpoint owners + creator).
- Optional query params for listing: `creator` (filter by creator wallet), `status` (active|draft|all), `limit`
- **Creator-scoped listing:** `GET /api/workflows?creator=0xYourWallet` returns only that creator's workflows.

4a) Workflow versioning
- Every workflow has an immutable version history. Creating a workflow seeds `v1`.
- List versions: `GET /api/workflows/{workflowId}/versions` → `{ versions: [...] }` (sorted newest first)
- Get a specific version: `GET /api/workflows/{workflowId}/versions/{versionIdOrNumber}`
- Create a new version (creator only): `POST /api/workflows/{workflowId}/versions` with `{ graph?, totalPrice?, splits?, mermaidDiagram?, executionMode?, changelog?, setDefault? }`
  - Omitted fields inherit from current workflow.
  - `setDefault: true` (default) promotes the new version as the live one.
- Promote/rollback an existing version: `PUT /api/workflows/{workflowId}/versions/{versionIdOrNumber}` with `{ setDefault: true }`
- Delete a non-default version: `DELETE /api/workflows/{workflowId}/versions/{versionIdOrNumber}`
- `PUT /api/workflows/{workflowId}` with changes to `graph`, `totalPrice`, or `splits` automatically creates a new version and bumps `currentVersion`. Include `changelog` in the PUT body to annotate it.

4b) Title/description edit cooldown
- `name` and `description` are rate-limited: each can only be changed **once every 7 days** per workflow. The rationale is to keep canonical links (e.g. https://www.apinow.fun/workflows/f5d40784593aa972) trustworthy.
- Server returns `429` with `{ error, retryAfterMs, retryAfterDays }` when cooldown is active.
- Before attempting a name/description update, check `nameUpdatedAt` / `descriptionUpdatedAt` on the workflow (returned by `GET /api/workflows/{workflowId}`). To iterate freely on behaviour, create a new **version** instead (no cooldown).

5) Create Endpoints (Agent Factory)
- Check factory access: `GET /api/user-factory/check-balance` (requires 10M $APINOW)
- Generate config from idea: `POST /api/user-factory/generate` with `{ "idea": "..." }`
  - Returns: `{ name, description, prompt, model, suggestedPrice, inputParams, outputParams, exampleInput }`
- Create endpoint: `POST /api/user-factory` with `{ name, prompt, description?, model?, usdcPrice?, recipientWallet?, inputParams?, outputParams? }`
  - Map `suggestedPrice` → `usdcPrice` from the generate output
- Test endpoint (free): `POST /api/user-factory/test-call` with `{ namespace, endpointName, input, saveExample: true }`
- Create markup workflow: `POST /api/user-factory/markup` with `{ endpointId, markupPercent?, markupAmount?, markupRecipient?, tokenBuyPercent?, tokenBuyRecipient?, tokenBuyCA? }`
- List your endpoints: `GET /api/user-factory` (with `x-wallet-address` header)

6) Spend controls
- Support request-scoped and session/day controls:
  - `max_per_query_usd`
  - `max_per_day_usd`
- Before each paid call, estimate/check endpoint price from details and enforce caps.
- If expected cost exceeds cap, stop and ask for confirmation or updated limits.

7) Signer support
- Private key (`APINOW_WALLET_PKEY`) default path.
- Managed signers (Privy/Bankr/CDP-style wallets) for SIWA/x402 setups where configured.

## Frontend Signer Pattern

Prefer server-side calls when you control a backend, worker, or agent runtime. For browser apps that need direct wallet-paid execution, reuse the connected wallet's `signTypedData`. This is the working pattern used in the `viniapp` example.

### Base chain requirement (x402)

Payments use USDC on **Base** with CAIP-2 network `eip155:8453` (chain ID `8453`, hex `0x2105`). The browser wallet **must be connected to Base** when the user signs the payment.

Setting `chain: base` in viem does **not** switch the wallet — only the wallet's active chain matters at sign time. If the wallet is on another network (e.g. Ethereum mainnet), libraries like viem will throw "Chain Id mismatch" while building the payment payload.

**What integrators must do:**
1. Before `signTypedData` / x402 payment flow, read `eth_chainId`.
2. If it is not `8453` / `0x2105`, call `wallet_switchEthereumChain` with `{ chainId: "0x2105" }`.
3. If the wallet returns error `4902` (unknown chain), call `wallet_addEthereumChain` with the Base RPC + explorer, then switch again.
4. Re-read `eth_chainId` and fail fast with a clear error if it is still not Base.
5. Re-check on **each call**, not just on "Connect" — users can change networks after connecting.

```tsx
import { useCallback, useMemo } from "react";
import { ExactEvmScheme, toClientEvmSigner } from "@x402/evm";
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";
import { useAccount, useWalletClient } from "wagmi";

const BASE_CHAIN_ID = 8453;
const BASE_CHAIN_ID_HEX = "0x2105";

async function ensureBaseChain() {
  const provider = (window as any).ethereum;
  if (!provider) throw new Error("No wallet detected");

  const chainId = parseInt(await provider.request({ method: "eth_chainId" }), 16);
  if (chainId === BASE_CHAIN_ID) return;

  try {
    await provider.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId: BASE_CHAIN_ID_HEX }],
    });
  } catch (err: any) {
    if (err.code === 4902) {
      await provider.request({
        method: "wallet_addEthereumChain",
        params: [{
          chainId: BASE_CHAIN_ID_HEX,
          chainName: "Base",
          nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
          rpcUrls: ["https://mainnet.base.org"],
          blockExplorerUrls: ["https://basescan.org"],
        }],
      });
    } else {
      throw err;
    }
  }

  const after = parseInt(await provider.request({ method: "eth_chainId" }), 16);
  if (after !== BASE_CHAIN_ID) throw new Error("Wallet is not on Base. Please switch manually.");
}

const corsSafeFetch: typeof fetch = (input, init) => {
  if (input instanceof Request) {
    input.headers.delete("Access-Control-Expose-Headers");
  }
  return fetch(input, init);
};

export function useX402Fetch() {
  const { address } = useAccount();
  const { data: walletClient } = useWalletClient();

  const fetchWithPayment = useMemo(() => {
    if (!walletClient || !address) return null;

    const publicClient = createPublicClient({
      chain: base,
      transport: http(),
    });

    const signer = toClientEvmSigner(
      {
        address: address as `0x${string}`,
        signTypedData: args => walletClient.signTypedData(args),
      },
      publicClient,
    );

    return wrapFetchWithPaymentFromConfig(corsSafeFetch, {
      schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(signer) }],
    });
  }, [walletClient, address]);

  return useCallback(
    async (input: RequestInfo | URL, init?: RequestInit) => {
      if (!fetchWithPayment) {
        throw new Error("Connect wallet before calling paid APINow endpoints.");
      }
      await ensureBaseChain();
      return fetchWithPayment(input, init);
    },
    [fetchWithPayment],
  );
}
```

Use that hook for direct frontend endpoint calls and workflow runs. `ensureBaseChain()` runs before every paid call automatically:

```tsx
const fetchWithPayment = useX402Fetch();

const endpointRes = await fetchWithPayment(
  "https://www.apinow.fun/api/endpoints/openai/chat",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ prompt: "Summarize this document" }),
  },
);

const workflowRes = await fetchWithPayment(
  "https://www.apinow.fun/api/workflows/90931d9c8fb94df9/run",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      recipient_interests: ["books", "cooking"],
      relationship: "friend",
      occasion: "birthday",
    }),
  },
);
```

## Execution Policy (must follow)

1. Never execute paid calls without payment credentials.
2. If allowlist mode is enabled, only call endpoints present in the selected list(s).
3. If allowlist mode is enabled, apply the same restrictions to discovery (`/api/endpoints` and `/api/endpoints/semantic-search`) before ranking/returning results.
4. Enforce `max_per_query_usd` and `max_per_day_usd` before every paid invocation.
5. Always fetch endpoint details before first call in a workflow to confirm method, params, and price.
6. When creating endpoints: always generate first (`factoryGenerate`), review the config (check name quality, schema coherence, prompt accuracy, price reasonableness), then create. Always run a test call and save an example before marking the endpoint as ready.
7. Prefer returning:
   - endpoint selected
   - price
   - auth method used (wallet or API key)
   - response payload summary

## Recommended Workflow

1. Discover
```bash
curl -X POST https://www.apinow.fun/api/endpoints/semantic-search \
  -H "Content-Type: application/json" \
  -d '{"query":"summarize long text","limit":5,"allowed_lists":["best-ai-tools"],"allowed_endpoints":["openai/chat"]}'

curl "https://www.apinow.fun/api/endpoints?search=summarize&sortBy=popular&allowed_lists=best-ai-tools&allowed_endpoints=openai/chat"
```

2. Inspect details
```bash
curl https://www.apinow.fun/api/endpoints/openai/chat/details
curl https://www.apinow.fun/api/endpoints/openai/chat/vibecode
```

3. Execute (server / agent wallet path)
```javascript
import { createClient } from "apinow-sdk";

const apinow = createClient({
  privateKey: process.env.APINOW_WALLET_PKEY,
});

const result = await apinow.call("/api/endpoints/openai/chat", {
  method: "POST",
  body: { prompt: "Summarize this document" },
});
```

4. Execute (frontend signer path)
```tsx
const fetchWithPayment = useX402Fetch();

const response = await fetchWithPayment(
  "https://www.apinow.fun/api/endpoints/openai/chat",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ prompt: "Summarize this document" }),
  },
);

const result = await response.json();
```

5. Execute (API key path)
```bash
curl -X POST https://www.apinow.fun/api/endpoints/openai/chat \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"prompt":"Summarize this document"}'
```

6. Browse workflows
```bash
curl "https://www.apinow.fun/api/workflows?status=active&limit=10"
curl https://www.apinow.fun/api/workflows/90931d9c8fb94df9
```

7. Run a workflow (server / agent wallet path)
```javascript
import { createClient } from "apinow-sdk";

const apinow = createClient({
  privateKey: process.env.APINOW_WALLET_PKEY,
});

const result = await apinow.runWorkflow("90931d9c8fb94df9", {
  recipient_interests: ["books", "cooking"],
  relationship: "friend",
  occasion: "birthday",
});
```

8. Run a workflow (frontend signer path)
```tsx
const fetchWithPayment = useX402Fetch();

const response = await fetchWithPayment(
  "https://www.apinow.fun/api/workflows/90931d9c8fb94df9/run",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      recipient_interests: ["books", "cooking"],
  relationship: "friend",
  occasion: "birthday",
    }),
  },
);

const result = await response.json();
```

9. Run a workflow (cURL)
```bash
curl -X POST 'https://www.apinow.fun/api/workflows/90931d9c8fb94df9/run' \
  -H 'Content-Type: application/json' \
  -H 'x-admin-key: YOUR_ADMIN_KEY' \
  -d '{"query": "hello world"}'
```

10. Run a workflow (CLI)
```bash
APINOW_WALLET_PKEY=0x... npx apinow run-workflow 90931d9c8fb94df9 -d '{"recipient_interests":["books","cooking"],"relationship":"friend","occasion":"birthday"}'
```

11. List a creator's workflows
```bash
curl "https://www.apinow.fun/api/workflows?creator=0xYourWallet&status=all"

# Or via CLI (uses your configured wallet):
APINOW_WALLET_PKEY=0x... npx apinow my-workflows
```

12. Workflow versions
```bash
# List versions
curl https://www.apinow.fun/api/workflows/f5d40784593aa972/versions
APINOW_WALLET_PKEY=0x... npx apinow workflow-versions f5d40784593aa972

# Create a new version (e.g. change price without touching metadata)
curl -X POST https://www.apinow.fun/api/workflows/f5d40784593aa972/versions \
  -H 'Content-Type: application/json' \
  -H 'x-wallet-address: 0xYourWallet' \
  -d '{"totalPrice":"0.12","changelog":"Raised price"}'

APINOW_WALLET_PKEY=0x... npx apinow workflow-version-create f5d40784593aa972 \
  --price 0.12 --changelog "Raised price"

# Promote/rollback to a version
APINOW_WALLET_PKEY=0x... npx apinow workflow-version-set-default f5d40784593aa972 3
```

13. SDK: version methods
```javascript
const apinow = createClient({ privateKey: process.env.APINOW_WALLET_PKEY });

await apinow.listMyWorkflows({ status: 'all' });
const { versions } = await apinow.listWorkflowVersions('f5d40784593aa972');
const v = await apinow.getWorkflowVersion('f5d40784593aa972', 2);

await apinow.createWorkflowVersion('f5d40784593aa972', {
  totalPrice: '0.12',
  changelog: 'Raised price after usage spike',
});

await apinow.setDefaultWorkflowVersion('f5d40784593aa972', 1); // rollback
```

## Workflow Example — "Tarot Gift"

A real workflow on APINow: [Tarot Gift](https://www.apinow.fun/workflows/90931d9c8fb94df9)

- **2 nodes**: `gg402/gift_recommender` → `ai-factory/tarot_card_reading`
- **Cost**: $0.05 USDC per call
- **Payment split**: 20% to gift_recommender owner, 16% to tarot_card_reading owner, 64% to workflow creator
- **Input**: `{ "recipient_interests": ["books", "cooking"], "relationship": "friend", "occasion": "birthday" }`
- **DAG**: gift_recommender runs first, its output feeds into tarot_card_reading

```javascript
const apinow = createClient({ privateKey: process.env.APINOW_WALLET_PKEY });

const details = await apinow.getWorkflow("90931d9c8fb94df9");
console.log(details.name);        // "Tarot Gift"
console.log(details.totalPrice);   // "0.05"
console.log(details.graph.nodes);  // [{id:"gift_recommender",...}, {id:"tarot_card_reading",...}]

const result = await apinow.runWorkflow("90931d9c8fb94df9", {
  recipient_interests: ["books", "cooking"],
  relationship: "friend",
  occasion: "birthday",
});
console.log(result);
```

## Create Endpoint Pipeline (Agent Factory)

Full flow: generate config from an idea → review → create → test → optional markup workflow with splits.

### SDK (one-shot pipeline)
```javascript
import { createClient } from "apinow-sdk";

const apinow = createClient({ privateKey: process.env.APINOW_WALLET_PKEY });

const result = await apinow.factoryPipeline(
  "Score startup pitches on 8 investor criteria",
  {
    recipientWallet: "0xYourWallet...",
    markup: {
      markupPercent: 30,
      markupRecipient: "0xYourWallet...",
      tokenBuyPercent: 10,
      tokenBuyRecipient: "0xYourWallet...",
      tokenBuyCA: "0xE5dd257baB19CB8Cb6B3628C09b62465eF4b2B07",
    },
  }
);

console.log(result.endpoint);    // { id, namespace, endpointName, price, tryUrl, apiUrl }
console.log(result.testOutput);  // saved example response
console.log(result.workflow);    // { workflowId, name, totalPrice, markupPercent, viewUrl }
```

### SDK (step-by-step with agent review)
```javascript
const apinow = createClient({ privateKey: process.env.APINOW_WALLET_PKEY });

// 1. Generate structured config from idea
const draft = await apinow.factoryGenerate("API that translates code between languages");
// draft = { name, description, prompt, model, suggestedPrice, inputParams, outputParams, exampleInput }

// 2. Agent reviews / tweaks the config (name quality, schema coherence, price)
const config = {
  name: draft.name,
  prompt: draft.prompt,
  description: draft.description,
  model: draft.model,
  usdcPrice: draft.suggestedPrice,
  recipientWallet: "0xYourWallet...",
  inputParams: draft.inputParams,
  outputParams: draft.outputParams,
};

// 3. Create the endpoint
const { endpoint } = await apinow.factoryCreate(config);

// 4. Test it and save an example
const test = await apinow.factoryTestCall({
  namespace: endpoint.namespace,
  endpointName: endpoint.endpointName,
  input: draft.exampleInput,
  saveExample: true,
});

// 5. Wrap with markup workflow (splits go to your wallet)
const { workflow } = await apinow.factoryMarkup({
  endpointId: endpoint.id,
  markupPercent: 30,
  markupRecipient: "0xYourWallet...",
});
```

### CLI
```bash
# One-shot pipeline: generate → create → test → markup
APINOW_WALLET_PKEY=0x... npx apinow factory-pipeline "Score startup pitches on 8 criteria" \
  --markup 30 --markup-recipient 0xYourWallet...

# Dry run (generate only, print config)
npx apinow factory-pipeline "Translate code between languages" --dry-run

# Step-by-step: generate → pipe → create
npx apinow factory-generate "Translate code between languages" > config.json
npx apinow factory-create --from-json config.json --recipient 0xYourWallet...

# Or pipe directly from stdin
npx apinow factory-generate "Translate code" | npx apinow factory-create --from-json - --recipient 0xYourWallet...
```

### cURL (step-by-step)
```bash
# Generate config
curl -X POST https://www.apinow.fun/api/user-factory/generate \
  -H "Content-Type: application/json" \
  -H "x-wallet-address: 0xYourWallet" \
  -d '{"idea":"Score startup pitches on 8 criteria"}'

# Create endpoint (use fields from generate response)
curl -X POST https://www.apinow.fun/api/user-factory \
  -H "Content-Type: application/json" \
  -H "x-wallet-address: 0xYourWallet" \
  -d '{"name":"startup_pitch_scorer","prompt":"...","description":"...","model":"google/gemini-2.0-flash-001","usdcPrice":"0.01","recipientWallet":"0xYourWallet"}'

# Test the endpoint (free)
curl -X POST https://www.apinow.fun/api/user-factory/test-call \
  -H "Content-Type: application/json" \
  -H "x-wallet-address: 0xYourWallet" \
  -d '{"namespace":"u-abc123","endpointName":"startup_pitch_scorer","input":{"pitch":"Our app uses AI to..."},"saveExample":true}'

# Create markup workflow with splits
curl -X POST https://www.apinow.fun/api/user-factory/markup \
  -H "Content-Type: application/json" \
  -H "x-wallet-address: 0xYourWallet" \
  -d '{"endpointId":"...","markupPercent":30,"markupRecipient":"0xYourWallet","tokenBuyPercent":10,"tokenBuyCA":"0xE5dd257baB19CB8Cb6B3628C09b62465eF4b2B07"}'
```

## List-Restricted Mode Template

When user asks for list-only querying, keep this state in the run:

```json
{
  "allowed_lists": ["best-ai-tools"],
  "allowed_endpoints": ["openai/chat", "gg402/horoscope"],
  "enforce_for_search": true,
  "enforce_for_semantic_search": true,
  "max_per_query_usd": 0.02,
  "max_per_day_usd": 1.0,
  "spent_today_usd": 0.00
}
```

Enforcement:
- Block call if endpoint is not in `allowed_endpoints`.
- For `GET /api/endpoints`, include `allowed_lists` / `allowed_endpoints` query filters.
- For `POST /api/endpoints/semantic-search`, include `allowed_lists` / `allowed_endpoints` in JSON body.
- Block call if endpoint price > `max_per_query_usd`.
- Block call if `spent_today_usd + endpoint_price > max_per_day_usd`.

## Config File (recommended)

Store this beside your installed skill as `apinow.config.json`:

```json
{
  "allowed_lists": ["best-ai-tools"],
  "allowed_endpoints": [],
  "enforce_for_search": true,
  "enforce_for_semantic_search": true,
  "max_per_query_usd": 0.02,
  "max_per_day_usd": 1.0
}
```

Usage notes:
- `allowed_lists` and `allowed_endpoints` are merged (union).
- If both are empty, discovery spans all public endpoints.
- Keep `enforce_for_search` and `enforce_for_semantic_search` true to avoid untrusted endpoints during discovery.

## Cross-Platform Install / Use

### Cursor
- Project skill location: `.cursor/skills/apinow/SKILL.md` or `.agents/skills/apinow/SKILL.md`
- Quick setup:
```bash
mkdir -p .cursor/skills/apinow && curl -fsSL https://www.apinow.fun/skill.md -o .cursor/skills/apinow/SKILL.md && cat > .cursor/skills/apinow/apinow.config.json <<'EOF'
{"allowed_lists":["best-ai-tools"],"allowed_endpoints":[],"enforce_for_search":true,"enforce_for_semantic_search":true}
EOF
```

### GitHub Copilot (agent skills)
- Project location: `.github/skills/apinow/SKILL.md` (or `.claude/skills/apinow/SKILL.md`)
- Quick setup:
```bash
mkdir -p .github/skills/apinow && curl -fsSL https://www.apinow.fun/skill.md -o .github/skills/apinow/SKILL.md && cat > .github/skills/apinow/apinow.config.json <<'EOF'
{"allowed_lists":["best-ai-tools"],"allowed_endpoints":[],"enforce_for_search":true,"enforce_for_semantic_search":true}
EOF
```

### Claude Code
- Project location: `.claude/skills/apinow/SKILL.md`
- Global location: `~/.claude/skills/apinow/SKILL.md`
- Quick setup:
```bash
mkdir -p .claude/skills/apinow && curl -fsSL https://www.apinow.fun/skill.md -o .claude/skills/apinow/SKILL.md && cat > .claude/skills/apinow/apinow.config.json <<'EOF'
{"allowed_lists":["best-ai-tools"],"allowed_endpoints":[],"enforce_for_search":true,"enforce_for_semantic_search":true}
EOF
```

### OpenClaw
- Workspace location: `skills/apinow/SKILL.md`
- Global location: `~/.openclaw/skills/apinow/SKILL.md`
- Quick setup:
```bash
mkdir -p skills/apinow && curl -fsSL https://www.apinow.fun/skill.md -o skills/apinow/SKILL.md && cat > skills/apinow/apinow.config.json <<'EOF'
{"allowed_lists":["best-ai-tools"],"allowed_endpoints":[],"enforce_for_search":true,"enforce_for_semantic_search":true}
EOF
```

## Notes

- Keep `APINOW_WALLET_PKEY` as canonical required env var for paid wallet flow.
- If using managed signers (Privy/Bankr/CDP), ensure those env vars are present before executing.

## Links

- Homepage: https://www.apinow.fun
- Skill file: https://www.apinow.fun/skill.md
- AI Skills page: https://www.apinow.fun/ai-skills
- SDK: https://www.npmjs.com/package/apinow-sdk
