diff --git a/documentation/README-embed-gospel-resources.md b/documentation/README-embed-gospel-resources.md
new file mode 100644
index 000000000..f7f7d32ec
--- /dev/null
+++ b/documentation/README-embed-gospel-resources.md
@@ -0,0 +1,47 @@
+# Embedding the gospel-resources map
+
+The map's **URL is its interface**. A partner embeds one address in an iframe and never touches it
+again, so every parameter below is a promise kept by a gate
+(`bun run check:embed-contract`), not a convention.
+
+```html
+
+```
+
+## The four addresses
+
+| Address | What the reader gets |
+|---|---|
+| `?codes=` | Only those languages' people groups, framed on them. Shows `74 / 2,107`, and that count is the button back to the whole map. |
+| `?country=` | That country's sheet open, framed on its groups. The country's own name also works (`?country=India`). |
+| `?code=` | The people group's sheet, with its resources. `&name=` and `&country=` disambiguate when a language has many groups. |
+| `?view=zero` | The groups with **nothing found** — the question this map exists for. `?view=gap` is the same view. |
+
+`?provider=maplibre` is not this map's parameter but the whole fleet's: it selects the keyless
+engine, and no map ever substitutes a different one (`bun run check:engine-contract`).
+
+## Bring your own list
+
+The join is **ISO 639-3**, the key every resource in this map is already joined on. A partner's list
+needs no agreement with Doxa's roster — only the codes their own data carries. That is the point:
+this corpus is public so that other lists can stand on it.
+
+Two things to know before you publish a link:
+
+- **The denominator is Doxa's roster.** The research corpus holds 12,379 people groups; this map
+ draws the **2,107** Doxa works, so `?codes=` intersects with those. A code outside the roster
+ draws nothing.
+- **It filters, it never invents.** A link matching none of its codes shows an empty map reading
+ `0 / 2,107`. That is the truth about the link — showing the full map instead would tell you your
+ broken list works.
+
+## What the map does not promise
+
+- **No zoom or centre parameter.** The frame is derived from the pins the link selects, so a link
+ stays correct when the data moves under it.
+- **Placement is approximate.** A dot marks where a *people* is found, not a town or a boundary,
+ and 108 of the placed groups share a coordinate with another group. The sheet says so in the
+ reader's language.
+- **An unknown parameter is ignored, never fatal.** `?country=ZZZ` renders the map, not an error —
+ a partner's typo must not break their page.
diff --git a/documentation/README.md b/documentation/README.md
index f68e6e3be..e3585bb84 100644
--- a/documentation/README.md
+++ b/documentation/README.md
@@ -14,6 +14,7 @@
- **[explanation.md](./explanation.md)** — the model in 15 lines.
- **[architecture/](./architecture/)** — the deep end: full contracts, the per-file catalog.
- **[README-embed-example.md](./README-embed-example.md)** — the drop-in README used when this bundler is embedded inside a host repo.
+- **[README-embed-gospel-resources.md](./README-embed-gospel-resources.md)** — the gospel map's URL contract for partner embeds: bring your own ISO 639-3 list, one country, one group, or the zero-access view.
Working on the repo: