# Resources and names

An account, a project, a website, a page, a block, a menu item, a media file, a setting: a
persisted thing with an identity, addressed by a name that spells out where it sits.

The name is the handle to store — not the URL, which carries a host and a version that may
change, and not the `display_name`, which is a label a person edits. Given a name, the URL
it is served at is a prefix away, which is why a client that keeps names can walk the
hierarchy without a table of endpoints:

```sh title="quickstart.sh"
account=$(curl_json "${auth[@]}" "$TENANT_API/tenant-api/v1/accounts" | jq -r '.accounts[0].id')
project=$(curl_json "${auth[@]}" \
  "$TENANT_API/tenant-api/v1/accounts/$account/projects" | jq -r '.projects[0].id')
website=$(curl_json "${auth[@]}" \
  "$TENANT_API/tenant-api/v1/projects/$project/websites" | jq -r '.websites[0].id')

site="$TENANT_API/tenant-api/v1/websites/$website"
```

## 5. Resources and resource names

A **resource** is a persisted thing with an identity. A **collection** is a set
of resources of one type, addressed by a plural `snake_case` id.

A **resource name** is the path from the root collection to the resource, with
no leading slash and no version:

```
websites/6a5e4957db9aab43d50bfd35
websites/6a5e4957db9aab43d50bfd35/cms_pages/507f1f77bcf86cd799439011
websites/6a5e4957db9aab43d50bfd35/cms_pages/507f1f77bcf86cd799439011/views/68b0c1
websites/6a5e4957db9aab43d50bfd35/settings/general.locale.default_language
accounts/64f0.../projects/64f1...
```

Rules:

- Collection ids are **plural**, `snake_case`, and identical to the path
  segment, the `name` field, and the List-response array field. One spelling.
- Names **alternate** collection id and resource id, always starting with a
  collection id and ending with a resource id (a singleton ends with its
  singular collection id — [§9](/concepts/methods)).
- A resource id is opaque to clients. Ours are Mongo ObjectIds, except
  `settings`, whose id is its dotted path, and `views`, whose overlay id is the
  view it overlays.
- Every resource MUST carry its own name in an output-only `name` field, and
  MUST also carry `id` — the final path segment, output-only. `id` is a
  documented convenience (D3); `name` is the
  identity.

## 6. URL mapping

A resource name maps to a URL by prefixing the surface and the version:

```
{surface}/{version}/{resource_name}
```

so `websites/{w}/cms_pages/{p}` is served at
`/tenant-api/v1/websites/{w}/cms_pages/{p}`, and a collection is the same URL
truncated after the collection id.

- Path parameters MUST be `snake_case` and MUST match
  the field they carry: `{website_id}`, never `{websiteId}`.
- A URL MUST NOT contain a verb as a path segment. Verbs are custom methods and
  use the `:` separator ([§10](/concepts/methods)).
- A URL MUST NOT contain a file extension.
- No trailing slash. A request with one gets `301` to the canonical form.
