---
title: "Your brand's words"
url: https://services.dev/docs/service/brand-words
captured: [brand-words.txt, gate-word-collision.txt]
---
# Your brand's words

URL: https://services.dev/docs/service/brand-words

> Brand.words renames the core's generic words on every surface your buyers, their agents and your members read. The core says job; your routes, events, commands, tools, SDK, Site, docs and apps say yours.

`Brand.words` answers one question: what does your brand call the things the core calls a job, a Task and a member?

## Smallest form

One key in `brand.ts`, beside the four-line Translation. `check` reads it back:

```bash
git add -A && git diff --staged
```

```txt title="magic values: none"
diff --git a/brand.ts b/brand.ts
index d78f630..cbf0f47 100644
--- a/brand.ts
+++ b/brand.ts
@@ -2,5 +2,5 @@ import { Brand } from 'services.dev'
 
 export default Brand({
   domain: 'lingua.example',
-  words: { job: 'order' },
+  words: { job: 'project' },
 })
```

```bash
npx services.dev check
```

```txt title="magic values: none"
brand.ts · 2 lines · lingua · lingua.example · words job → project
✓ ready to sell · 1 Service · AI delivers it alone · it keeps at least 80% of every job
```

## Every form

**On the brand**

| Key | Written | Left out | Does |
|---|---|---|---|
| `words` | `{ <generic word>: string }` | none | The brand's own words for the generic ones, on every Layer B surface: paths, events, commands, tools, SDK names, docs, the Site and the apps. Each plural is the word's own. |
| `also` | `{ <op id>: path \| path[] }` | none | Paths of the brand's own at which an operation is also served, beside the row's: `{ 'member.ledger.get': '/conflicts' }`. A declared column of the operation registry, like `words`: the same handler, the same callers, in the HTTP column of every surface that renders it. An id that names no operation, or a path that collides with one services.dev serves, fails word_collision. |

**The generic words a brand may rename on its own surfaces.**

| Generic word | Many |
|---|---|
| `job` | `jobs` |
| `subject` | `subjects` |
| `task` | `tasks` |
| `member` | `members` |
| `pool` | `pools` |
| `end` | `ends` |
| `ask` | `asks` |
| `step` | `steps` |
| `client` | `clients` |
| `buyer` | `buyers` |

## The core says job, your surfaces say yours

`client` is the party whose matter it is and `buyer` the party who pays; a brand where they are always one party gives both one word, as the sales brand names each the seller, and `word_repeated` allows that pair alone. The core, these docs and every op id keep the generic words. Your surfaces render yours. The worked legal brand sets six words, and each row renders in them:

```bash
cat brand.ts
```

```txt title="magic values: none"
  words: { job: 'matter', subject: 'asset', task: 'review', member: 'signer', pool: 'network', end: 'outcome' },
http   GET /jobs/:id             → GET /matters/:id            ✓ a route
cli    jobs get                  → matters get                 ✓ a command
mcp    get_job                   → get_matter                  ✓ a tool in tools/list
sdk    jobs.get()                → matters.get()               ✓ a method
http   POST /jobs                → POST /matters               ✓ a route
cli    contract-review           → contract-review             ✓ a command
mcp    order_contract_review     → order_matter                ✓ a tool in tools/list
sdk    contractReview.order()    → contractReview.order()      ✓ a method
emits  job.ordered, charge.held  → matter.ordered, charge.held ✓ on GET /events, after the order below
```

Each row of the contract renders once per word: the path takes the plural, an event the singular, a CLI command the plural, an MCP tool the singular and an SDK namespace the plural. The manifest carries both columns, so an agent reading it knows `job.get` by either name:

```txt
→ GET /manifest.json
```

```txt title="magic values: none"
  words.job     {"generic":{"one":"job","many":"jobs"},"brand":{"one":"matter","many":"matters"}}
  rendered      46 rows · "job.get": {"http":"GET /matters/:id","cli":"matters get <matter>","mcp":"get_matter","sdk":"matters.get()"}
```

An order, its next call and its feed then speak the brand's words, and so does every refusal, with its page at the brand's own origin:

```txt
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"ada@example.com"},"client_region":"US-CA","max_usd":99,"key":"lease"}
```

```txt title="202 · job_7Hq2 · working · $99.00 held · magic values: none"
  next    {"do":"get","arguments":{"id":"job_7Hq2"},"tool":"get_matter","http":"GET http://localhost:8787/matters/job_7Hq2?wait=50"}
→ GET /events
← matter.ordered · charge.held
```

```txt
→ GET /matters/job_none
```

```txt title="magic values: none"
← 404 not_found: No matter job_none.
  doc_url https://api.lawyer/docs/errors/not_found
```

Every surface follows: the routes in `openapi.json`, the MCP tools, the generated SDK, the CLI's help, `llms.txt` and the Site. [What the brand gets](https://services.dev/docs/examples/legal/surfaces.md) prints every one.

`also` serves a row at a path of your own beside the rendered one, so a brand porting an existing API keeps its old paths. Renaming happens only here: nothing else in a Service can rename a generic word.

## When two things would read the same

A brand word may not take a generic word, a word an op id is spelled with, or a path services.dev already serves. `check` fails `word_collision`, names the word and the row it collides with, and reads every other gate in the generic words until you choose another:

```bash
npx services.dev check
```

```txt title="magic values: none"
brand.ts · 2 lines · lingua · lingua.example · words job → order
  ✗ A Brand.words value takes a generic word, a word an operation's id is spelled with or a path services.dev already serves, or makes two rows render the same, so two things would read the same. Choose a word of your own for it. words.job is 'order', a word of the operation service.order.
    https://services.dev/docs/reference/check/word_collision
✗ 1 to fix
  next    Choose a word of your own for it. words.job is 'order', a word of the operation service.order.
```

## Refusals

| `check` gate | Why |
|---|---|
| [`word_collision`](https://services.dev/docs/reference/check/word_collision.md) | A Brand.words value takes a generic word, a word an operation's id is spelled with or a path services.dev already serves, or makes two rows render the same, so two things would read the same. |

| When the file won't load | Thrown by | Why |
|---|---|---|
| [`word_repeated`](https://services.dev/docs/reference/definition-errors.md#word_repeated) | `Brand()` | Brand: words.job and words.task are both 'order', so two things would read the same. |
| [`word_unlowercase`](https://services.dev/docs/reference/definition-errors.md#word_unlowercase) | `Brand()` | Brand: words.job is 'Matter'. A word is lowercase letters and hyphens, and its plural is made for it: 'matter'. |
| [`also_unknown`](https://services.dev/docs/reference/definition-errors.md#also_unknown) | `Brand()` | Brand: also names 'matters', which isn't an operation id: write it as the registry does, such as 'member.ledger.get'. |

---

- Up: [Service()](https://services.dev/docs/service.md)
- Previous: [Brand()](https://services.dev/docs/service/brand.md)
- Next: [The manifest](https://services.dev/docs/service/manifest.md)
