# Using an API key

Some of what this site answers is for programs rather than people: reading a game's feedback queue,
publishing wiki documents, uploading a build. Those endpoints are opened by an **API key**, and this
is how one is presented and what the answers mean.

Nothing here is module-specific. Every key works the same way wherever it is accepted.

---

## Presenting one

**Always a header. Never the URL, never the body, and never a query string.**

```
X-Api-Key: dm_14_9f3c1a...
```

The header name is exactly `X-Api-Key`. That is the only place a key is read from, on every
endpoint, whatever the method - so a `GET` and a `POST` carry it identically and there is nothing to
look up per call.

An address is not a private place: it is written into server logs, into browser history, into the
`Referer` header of anything the page then loads, and into whatever proxy sits between you and here.
A key in a query string is a key you have published, which is why this site will not read one from
there even as a convenience.

```bash
curl -H "X-Api-Key: $KEY" https://www.dasmaffin.com/Tgsc/api/reports

curl -H "X-Api-Key: $KEY" -H "Content-Type: text/html" \
     --data-binary @packaging.html \
     https://www.dasmaffin.com/Mccp/api/wiki/packaging
```

The method is whatever the endpoint's own document says - `GET` to read, `POST` to publish, `DELETE`
to remove. The key does not change it.

## Checking one without changing anything

```
GET /api/mccp/key
X-Api-Key: <your key>
```

`200 {"ok":true,"says":"That key works. Nothing was changed."}` if the key is valid at all. It
writes nothing, so it is safe to call from a health check or while setting a pipeline up.

It answers about the key itself, not about what that key may reach: a valid key granted nothing you
are about to call still gets `200` here and `401` there.

## What a refusal means

| Answer | What happened |
| --- | --- |
| `401 {"error":"no_api_key"}` | No `X-Api-Key` header arrived at all. Usually the client, or a shell eating the header - not a bad key |
| `401 {"error":"unknown_api_key"}` | A key arrived and does not open this: a typo, a revoked key, or one not granted this backend. Deliberately not told apart |
| `403` | You are signed in as a person and lack the permission. Nothing to do with keys |
| `404` | The key is fine and the thing you asked for is not there - or belongs to a module this key was not granted |

**The first two are worth telling apart in your own logs.** They were one bare `401` once: a
publish came back refused, the agent concluded its key had been rotated and stopped publishing, and
what had actually happened was its own shell dropping the header so no key ever arrived.

A key that arrived and does not open the thing is not told apart from a key that does not exist, on
purpose. Distinguishing them would let somebody with a list of guesses learn which ones are real.

## Getting one

Keys are given out from the site's permissions page by somebody who holds **Give out API keys**.
Each one is granted specific backends, one by one - `Tgsc:reports`, `Mccp:wiki` - so a key trusted
with one game's queue has not been trusted with another's, or with the wiki.

Ask for a key naming what it is for. The name is shown wherever the key acts on your behalf: an
answer posted to a player's report is authored as the key's name, so "MCCP build agent" reads
better next to "Answered" than "key 14" does.

## Keeping one

- **It is shown once**, when it is created. The site stores a hash, so a lost key is replaced
  rather than recovered.
- **It is a password.** Not in a repository, not in a CI log, not in a screenshot. In whatever your
  side uses for secrets.
- **It can be edited or revoked** at any time from the same page, without a new key being issued -
  what a key opens can change while the key string stays the same.
- **One key per program**, not one shared between several. That is what makes revoking one of them
  a thing you can do without stopping the others.

## Documents behind a key

A document describing a key-only API is itself behind the key - `/docs/reports/reading.md`, for
instance. It is served to a program the same way as anything else:

```bash
curl -H "X-Api-Key: $KEY" https://www.dasmaffin.com/docs/reports/reading.md
```

Opened in a browser instead, the same address without `.md` asks you to sign in, and shows the page
to anybody who could give a key out. Two doors, because a program cannot sign in and a browser
cannot easily send a header.
