# Concepts ## Workspaces Everything belongs to a **workspace** (an organization): domains, API tokens, the wallet, the activity log, and the contact book. A user can belong to several workspaces and switch or create them from the dashboard sidebar. API tokens are bound to one workspace — a token can never see another workspace's data. ## Contacts Every domain names a contact in each of four registry roles — **registrant** (the legal owner, shown in whois), **admin**, **technical**, and **billing**. A workspace keeps a **contact book** (dashboard → Contacts) and points domains at entries from it. One entry is the **default**: it's used for all four roles on new registrations and transfers. Admin, technical and billing can be reassigned per domain from the domain's Contacts tab. The registrant cannot — changing it is a registry trade with its own legal flow. A contact can be an individual or an **organization (legal entity)** with company and VAT numbers — use the legal entity when the domains belong to a company and billing should reflect it. Editing a contact updates the whois record of every domain already using it. ## The wallet Each workspace has a EUR wallet. Every purchase — registration, renewal, transfer — debits it. Money comes in by topping up (dashboard → Billing) or per-call pay-as-you-go (see [Payments](/docs/payments)). If a registry operation fails after a pay-as-you-go charge, the credit stays on the wallet and the retry doesn't re-charge your card — no refund round-trips. Some workspaces are on **invoiced (postpaid) billing** by arrangement: purchases accrue against the wallet and are invoiced monthly instead of requiring an upfront balance. ## Explicit price confirmation Every spending call requires `confirm_price` — the total you saw quoted. The server re-resolves the live price and refuses on any mismatch (`409 price_changed`, carrying the current price). This is the core agent-safety contract: an agent can never be surprised by a charge, and a stale quote can never silently spend more than intended. Destructive operations have the same explicitness: deleting a domain requires naming it again, and the CLI refuses spending/destructive verbs without explicit flags. ## API tokens Tokens look like `ingram_live_…`, are stored hashed (shown once at mint time), carry a scope (`read` or `write`), and authenticate REST and MCP via `Authorization: Bearer`. Mint them at signup (`POST /api/v1/accounts`) or in the dashboard (**Settings → API tokens**). ## The four surfaces | Surface | Where | Notes | |---|---|---| | REST API | `/api/v1` | The source of truth; [OpenAPI](https://domains.ingram.tech/api/v1/openapi.json) emitted from the route schemas | | MCP server | `/api/mcp` | Same operations as tools for MCP clients — see [Agents](/docs/agents) | | CLI | `npm i -g @ingram-tech/domains` | Wraps the REST API 1:1 — see [CLI](/docs/cli) | | Dashboard | domains.ingram.tech | One client among several, plus an in-app assistant for non-billable operations | All four hit the same domain logic with the same safety contract; nothing is dashboard-only except viewing invoices and topping up by card.