---
name: groats
description: One balance for paid APIs. Your agent finds a tool, reads its schema, runs it, and pays per call out of one balance — no per-vendor signup, no card per API. Use this when the user asks for something a paid API does and you have no key for it.
when-not-to-use: If the user already has a dedicated MCP server, an API key or a tool for that specific service, use theirs. This is for the calls you would otherwise have to tell the user you cannot make.
metadata:
  version: 0.1.0
  client: groats
  install: npm install -g groats
  gateway: https://api.groats.dev
  page: https://groats.dev/skill.md
---

# groats

You are an agent. This page tells you how to buy one API call with money that is
already loaded, and how to be honest with your user about what it cost.

**This page and the `groats` client carry the same version.** If they disagree,
update both halves — `npm install -g groats@latest`, then fetch this page again.
**Never downgrade one to match the other.** A pinned old half is how an agent
ends up sending a command the Gateway reads differently.

## The line your user pasted

> Read https://groats.dev/skill.md and follow it: install the groats client, register yourself, then find a tool and run it.

Everything below is yours to do. Ask your user for nothing except the one sign-in
in step 3, and never ask them to paste anything back to you.

## Workflow

### 1. Install the client

```bash
npm install -g groats
```

Every command below takes `--json` and prints **one** JSON object when you pass
it — never prose in front of it. Use `--json`: it is the machine-readable half,
and the human-readable lines are for your user.

Check that your copy of this page and the client agree:

```bash
groats version --check
```

If they disagree, update both halves. Never downgrade one to match the other.

### 2. Register yourself

```bash
groats register --json
```

This is the one call that needs no credential. It mints an **API key** that
never expires, stores it on this machine, and hands back a claim address. The
client can hold more than one key — one per agent is the convention — and
`--key-name` names the one you are storing or using.

**Never ask your user to copy a key, a code or a token back to you.** You have
the key already.

### 3. Tell your user, once, to claim the account

Say it in your own words. It is one hosted sign-in with Google or GitHub, about
twenty seconds, and it releases $1 of free credit. Until then you may `discover`,
`inspect` and read `balance`; a priced `run` is refused with exit code 3.

Hand them the `claimUrl` from step 2. Do not ask them to paste anything back.

### 4. Find a tool

```bash
groats discover "neural web search" --limit 5 --json
```

Ask for **5 to 10 results**, and **one search term at a time**. A wide search
costs nothing and tells you less.

Each result carries a price shape, a health standing and whether the tool is
verified. **Use health to break a tie between two tools that both fit. Never use
it to filter**: the Gateway has already hidden what it judged uncallable, so a
tool you see is one it will let you call.

### 5. Read the tool before you run it

```bash
groats inspect api.exa.ai/search --json
```

**`inspect` is not optional.** One paid call in five comes back with nothing
usable, and 8 of those 10 failures are caused by the listing's own declared
parameters rather than by a broken service. `inspect` is free and it is the step
that catches them. Read `input.schema`, `input.required` and `exampleParameters`
and send what they say.

A tool priced **per item returned** cannot be quoted before the call. Ask for 5
to 10 items on the first call and read what it actually cost.

### 6. Run it

```bash
groats run api.exa.ai/search --input '{"query":"x402 tools","numResults":5}' --json
```

The client generates the request id from the command you typed, so **repeating
the identical command sends the identical id** and a retry after a dropped line
returns the original call instead of paying twice. If you mean to make a second,
genuinely new call of the same tool with the same input, pass your own
`--request-id`.

Every answer carries the same three facts, in the same place, whatever happened:

| Fact | Field | What it is |
|---|---|---|
| Provider outcome | `provider` | what the provider said, unaltered, including its real HTTP status |
| Judged outcome | `judged` | what we made of it, with a reason when it failed |
| Charged | `charged` | whether the balance moved, and by how much, in USD |

Read `charged` before you tell your user anything about cost. A provider HTTP
200 carrying an error object is a `judged: failed` that moved no money.

Large answers: `--out answer.json` writes the provider's answer to a file and
keeps it out of your context.

### 7. Come back for a slow call

A call that outlives about thirty seconds hands you a **call number** and
`"running": true` instead of an answer. Do not hold the line open.

```bash
groats runs get 5a0d0e4e-9c6a-4a4f-9d3a-3b7a0f4b1c2d --json
```

Fetch it **every 5 to 10 seconds** until the status is `finished`. Passing `--wait` does the same loop for you. A dropped connection never loses a call you
have already paid for.

### 8. Know where you stand

```bash
groats balance --json
groats runs list --limit 10 --json
```

`runs list` shows what each recent call cost, what we judged and which of your
keys made it.

## Error handling

| What you see | What it means | What to do |
|---|---|---|
| `refused (missing-field)` | the input has no value for a field the tool requires | read the schema with `inspect` and send the field |
| `refused (wrong-type)` | a field is clearly the wrong type | fix that one field; the refusal names it |
| `refused (insufficient-balance)` | the account balance cannot fund this call | tell your user to top up |
| `refused (above-ceiling)` | this call costs more than this key's per-call ceiling | tell your user which limit it was |
| `refused (budget-exhausted)` | this key has spent its budget; the account balance may be fine | tell your user which key it was |
| `refused (account-unclaimed)` | nobody has claimed this account yet | hand your user the claim address again |
| `refused (unknown-tool)` | no tool has that name | find one with `discover` |
| `"running": true` | the call outlived the line | fetch it by its call number |
| `judged: failed` | the provider answered and we judged it a failure | read `charged`: a failure moves no money. Pick another tool |
| `version mismatch` | this page and the client disagree | update both halves. Never downgrade one to match the other |

None of these is decided by the client. It relays what the Gateway said.

## CLI adapter

| Command | Invocation |
|---|---|
| register | `groats register --json` |
| discover | `groats discover "neural web search" --category Web --limit 5 --json` |
| inspect | `groats inspect api.exa.ai/search --json` |
| run | `groats run api.exa.ai/search --input '{"query":"x402 tools"}' --json` |
| runs get | `groats runs get 5a0d0e4e-9c6a-4a4f-9d3a-3b7a0f4b1c2d --json` |
| runs list | `groats runs list --limit 10 --json` |
| balance | `groats balance --json` |

### Exit codes

| Code | Meaning |
|---|---|
| 0 | success — read `charged`, the balance may or may not have moved |
| 1 | usage error: the client could not read what you typed |
| 2 | refused before any provider was paid |
| 3 | not connected, or the account is not claimed |
| 4 | insufficient balance |
| 5 | the provider failed and we judged it a failure |

Branch on the exit code rather than on the prose.

### Keys and version

`groats keys list` and `groats version` are the client's own lines: they reach
the Gateway as nothing and are not among the six commands.

The client holds more than one key.

```bash
groats keys list --json
groats register --key-name research-agent --json
groats discover "weather" --key-name research-agent --json
```

Every call records the key that made it, so spend is attributable per agent and
one key can be capped or switched off without touching the others.

## HTTP adapter

Registration and the free commands, if you have no terminal. `run`, `runs get`
and `runs list` go through the client or the MCP server, which is where the
retry-safe request id and the fetch loop live. The API key goes in the header
and nothing else is needed.

| Command | Request |
|---|---|
| register | `POST https://api.groats.dev/api/register` |
| discover | `GET https://api.groats.dev/api/discover?query=neural+web+search&category=Web&limit=5` |
| inspect | `GET https://api.groats.dev/api/inspect?name=api.exa.ai/search` |
| balance | `GET https://api.groats.dev/api/balance` |

```
Authorization: Bearer groats_sk_...
```

Every answer is the same JSON the client prints with `--json`. It is the same
command reaching the same Gateway: the client decides nothing the HTTP surface
does not.

## MCP adapter

The remote MCP server exposes the same six commands one-to-one, at
`https://api.groats.dev/api/mcp`. It admits either an API key in a header or a
hosted sign-in, and both resolve to the same account, so switching agents does
not mean starting over.

## What the client will not do

The client never decides a price, never ranks tools and never decides whether a
call is billable. It relays the six commands, fetches a slow call on a loop,
writes an answer to a file, and holds your keys. Everything about money is
decided by the Gateway and reported to you, so a client that is months old is
never wrong about what you were charged.
