# Ideal Postcodes CLI

`idpc` is the official command line interface for Ideal Postcodes. It manages API keys, cleanses messy addresses, validates emails and phone numbers, and resolves specific addresses from partial queries.

It is built for LLM agents (Claude Code, Cursor, Codex) and CI/CD pipelines, and works equally well from a terminal.

## Installation[​](#installation "Direct link to Installation")

```
npm install -g @ideal-postcodes/cli

idpc --version
```

## Agent protocol[​](#agent-protocol "Direct link to Agent protocol")

The CLI auto-detects non-TTY environments and emits JSON — no `--json` flag needed when piping or running headless.

* Supply ALL required flags. The CLI will NOT prompt when stdin is not a TTY.
* `-q, --quiet` suppresses status output and implies `--json`.
* Exit `0` means success, `1` means error.
* Both success and error JSON go to **stdout** — parse it uniformly, then check for an `error` key and the exit code:
  <!-- -->
  ```
  {"error":{"code":"...","message":"...","details":{}}}
  ```
* Destructive commands (e.g. `keys configs delete`) require `--yes` in non-TTY.
* Use env vars or flags in automation. Never rely on `idpc auth login` from an agent.

## Authentication[​](#authentication "Direct link to Authentication")

Two credentials: `api_key` (required) and `user_token` (required for `/keys/*` reads, configs, and updates). Each credential resolves independently, in this order:

| Priority    | Source                                                                      |
| ----------- | --------------------------------------------------------------------------- |
| 1 (highest) | `--api-key <k>` / `--user-token <t>`                                        |
| 2           | `IDPC_API_KEY` / `IDPC_USER_TOKEN` env var                                  |
| 3 (lowest)  | `~/.config/ideal-postcodes/credentials.json` (written by `idpc auth login`) |

A missing api\_key returns error code `missing_api_key`. A missing user\_token on a command that needs it returns `missing_user_token`.

## Global flags[​](#global-flags "Direct link to Global flags")

| Flag               | Description                          |
| ------------------ | ------------------------------------ |
| `--api-key <k>`    | Override API key for this invocation |
| `--user-token <t>` | Override user token                  |
| `--json`           | Force JSON (automatic in non-TTY)    |
| `-q, --quiet`      | Suppress status, implies `--json`    |
| `--base-url <url>` | Override API base (diagnostics only) |

## Commands[​](#commands "Direct link to Commands")

| Group                                                                       | Subcommands                                                                            |
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [`idpc auth`](https://docs.ideal-postcodes.co.uk/docs/cli/auth)             | `login`, `logout`, `whoami`                                                            |
| [`idpc keys`](https://docs.ideal-postcodes.co.uk/docs/cli/keys)             | `get`, `details`, `update`, `usage`, `logs`, `configs {list,get,create,update,delete}` |
| [`idpc cleanse`](https://docs.ideal-postcodes.co.uk/docs/cli/cleanse)       | Cleanse one address, a file, or stdin                                                  |
| [`idpc email`](https://docs.ideal-postcodes.co.uk/docs/cli/email)           | Validate one email, a file, or stdin                                                   |
| [`idpc phone`](https://docs.ideal-postcodes.co.uk/docs/cli/phone)           | Validate one phone number, a file, or stdin                                            |
| [`idpc find` / `resolve`](https://docs.ideal-postcodes.co.uk/docs/cli/find) | Autocomplete then resolve a suggestion id to a full address                            |
| `idpc doctor`                                                               | Print environment info, verify connectivity, and check key usability                   |

Run `idpc <command> --help` for full flags.

## Common pitfalls[​](#common-pitfalls "Direct link to Common pitfalls")

* **`user_token` is separate from `api_key`.** `keys details`, `keys usage`, `keys logs`, `keys update`, and all `configs` commands require both.
* **`cleanse`, `email`, and `phone` cost paid lookups.** The public test key `iddqd` returns `auth_failed`.
* **Batch mode emits CSV** unless `--json` is passed; a single query always emits JSON.
* **`find` without a query in non-TTY errors.** Always pass a query when scripting.
* **`keys logs` emits raw CSV**, not JSON, and rejects `--json` / `-q` with `invalid_input`. Redirect to a file or pipe into your CSV tooling.
* **The credentials file is `0600`.** If your umask is unusual, `idpc auth login` may fail with `write_failed`.

## Quick examples[​](#quick-examples "Direct link to Quick examples")

```
# Cleanse one address (JSON to stdout)

idpc cleanse "10 downing street, london"



# Batch cleanse

cat addresses.txt | idpc cleanse --stdin



# Validate an email or phone number

idpc email "support@example.com"

idpc phone "+442071128019" --carrier



# Batch validate emails to a CSV

cat emails.txt | idpc email --stdin > emails.csv



# Find a specific address and resolve it

ID=$(idpc find "10 downing" | jq -r '.suggestions[0].id')

idpc resolve "$ID"



# Inspect a key

idpc keys details
```
