# What the standard guarantees

The reference documents every endpoint. These pages document the rules *all* of them
obey — which is the more useful half, because it lets you predict an endpoint you have not
read yet: what its URL looks like, what a write returns, how its list is paged and
filtered, what its failures look like, and what it does when the work outlives the call.

They are the platform's own API standard, the normative document its code is reviewed
against, transcluded here at build time. Not a summary of it, and not a second copy: the
same file, minus the sections that concern only the people implementing it — which is why
the numbering below has gaps in it.

The transport is ordinary REST over JSON — no protobuf, no transcoding, nothing a `curl`
user cannot read. The semantics come from
[Google's API Improvement Proposals](https://google.aip.dev), which is why an endpoint you
have never seen behaves the way you expect it to. Where this API departs from them it says
so, in the table of deviations below; their labels, D1 to D6, are how the rest of these
pages refer to them.

## 1. The one sentence

Every endpoint is one of **five standard methods** or a **named custom method**
on a **resource** that has a **hierarchical name**, requests and responses are
**snake_case JSON**, lists are **paginated with `page_size`/`page_token` and
filtered with `filter`**, and every failure is a **`google.rpc.Status` body**
with a canonical code.

## 3. Deliberate deviations from AIP

These are permanent and load-bearing. Everything not listed here follows the
AIP as written; when in doubt, the AIP wins.

| # | AIP says | We do | Why |
|---|---|---|---|
| D1 | Collection ids and JSON fields are `lowerCamelCase` (AIP-122/140, proto3 JSON mapping) | **`snake_case` everywhere** — path segments, fields, query params, custom-method verbs | AIP-140 defines field names as `lower_snake_case`; camelCase is purely an artifact of proto3→JSON transcoding, which we do not do. Our models, our Mongo documents and our existing JSON are already snake_case. One spelling, end to end. |
| D2 | Resource names carry the **full** ancestry (`accounts/a/projects/p/websites/w/cms_pages/c`) | Names are rooted at the **nearest globally-addressable ancestor**: `websites/{website}/cms_pages/{cms_page}` | Every id is a Mongo ObjectId and therefore globally unique, so the extra ancestry adds no addressing power, only length. `website.parent` carries the link upward for anyone who needs it. |
| D3 | Fields that reference another resource hold its **resource name** (AIP-122) | References stay **bare ids** in `<field>_id` / `<field>_ids` fields, each documenting its resource type | 26 distinct reference fields across 33 models, all resolvable within a scope the URL already fixes. |
| D4 | Create returns `200 OK` | Create returns **`201 Created`** with a `Location` header | The transport is REST, not transcoded gRPC. 201 + Location is what REST clients and caches already understand. |
| D5 | Output-only fields sent on a write are silently ignored (AIP-203) | Ignored **by default**; a resource MAY declare a field `IMMUTABLE` instead and reject it with `INVALID_ARGUMENT` | Silent-ignore is the AIP rule and the default. Where the team has already decided a silent drop is a footgun (`menu_item.sort_order`), `IMMUTABLE` is the sanctioned escape hatch — it is explicit, not ad-hoc. |
| D6 | `error.details` entries are `Any`-typed with `@type` URLs | `details` entries are plain objects with a `"type"` **string** discriminator from a closed set ([§13](/concepts/errors)) | No type registry to publish or resolve. Same information, readable without tooling. |

## 23. AIP index

Adopted as written: 121 (resource-oriented design), 122 (names, except D2/D3),
126 (enums), 131–135 (standard methods, except D4), 136 (custom methods), 140
(field names, per D1), 142 (time), 143 (standardized codes), 148 (standard
fields), 151 (operations), 154 (etags), 155 (request ids), 156 (singletons),
157 (partial responses, optional), 158 (pagination), 160 (filtering, subset per
[§8](/concepts/lists)), 163 (validate-only), 180 (compatibility), 185 (versioning), 193 (errors,
except D6), 203 (field behavior, except D5), 216 (states), 231/234 (batch
methods).

Not adopted: everything proto/gRPC-specific (191–192 file layout, 213 common
components, `google.protobuf` wrappers), 127 (HTTP transcoding annotations),
and the `Any`-typed error details of 193 (see D6).
