# Your own providers

A Provider organization registers the providers it runs and which of the models Momor lists they serve. Once Momor approves a provider, routing and the public catalogs reach it.

## Roots and regions

A provider is a root, which holds its name, or a region under a root. The Provider organization's owner, signed in, manages
them, and a provider is changed only by the organization that registered its root. A new root waits for Momor to
approve it: until then it and its regions are listed in `GET /providers` and take models, but neither routing nor the
public catalogs reach them. Approval reaches routing within five minutes. Once a root is approved, routing sees a
change to it or its regions as soon as it is saved; the public catalogs (`GET /models/...`) may answer from a copy up
to five minutes old.

| Endpoint | What it does |
|---|---|
| `GET /providers` | The organization's roots and regions, approved or not, by name and region, each with the models it serves and their operations, a page at a time as `{ "count", "items" }`: `skip` passes over that many providers (0 by default) and `take` sets how many a page holds, from 1 to 200 (50 by default). |
| `PUT /providers/{name}` | Registers a root, or replaces how one is reached. The models it serves and its regions stay as they are, and so does whether it is approved, which the answer's `approved` says. |
| `DELETE /providers/{name}` | Removes a root with every model it serves, once none of its regions remains (`409` while any does). |
| `PUT /providers/{name}/regions/{region}` | Registers a region under the organization's root, or replaces how it is reached. |
| `DELETE /providers/{name}/regions/{region}` | Removes a region with every model it serves. |
| `PUT /providers/{name}/models/{publisher}/{model}` | Puts a model Momor lists on the root, or replaces how the root serves it. A model Momor does not list is `404`. |
| `DELETE /providers/{name}/models/{publisher}/{model}` | Takes a model off the root. |
| `PUT /providers/{name}/regions/{region}/models/{publisher}/{model}` | Puts a model Momor lists on the region, or replaces how the region serves it. |
| `DELETE /providers/{name}/regions/{region}/models/{publisher}/{model}` | Takes a model off the region. |

`name` is the root's name, which callers give in `model.provider`, `prioritization` and `keys`, matched without regard
to case. A name has one root across every organization: the first organization to register it holds it, a name
another organization holds is `409`, and removing the root frees the name. A root may name the region it serves from
in its body. A region carries its root's name and takes what a key comes with from it, and where and how its models
are reached from it wherever the region says nothing; it serves only the models put on it. A region needs its root
first (`400` without one), and a root another organization holds is `404`. A caller's name always reaches the root;
an unpinned selection reaches the regions too, and a region runs on the key saved for, or Momor's key for, its root
where none is held for the region itself.

## Register a provider

```json
PUT /providers/hostly
{
  "defaultBaseUrl": "https://-region-.hostly.example/v1/",
  "defaultAuthentication": "Bearer",
  "defaultHostSettings": { "reasoningField": "reasoning", "maxTokensField": "max_tokens" },
  "keyFields": ["region"],
  "fieldPatterns": { "region": "^[a-z]+$" },
  "enabled": true
}
```

| Field | Notes |
|---|---|
| `region` | The region a root serves from, where it names one. A region's own region is named by its route. |
| `defaultBaseUrl` | The https address calls go to unless a model names its own. A host label written as `-name-` is filled from the value of that name the key comes with: a key with `region` set to `west` reaches `https://-region-.hostly.example/v1/` at `https://west.hostly.example/v1/`. |
| `defaultAuthentication` | How the key is presented unless a model says otherwise: `Bearer`, the default, `Header:name`, `Query:name` or `ServiceAccount`. |
| `defaultHostSettings` | What the host does differently from its protocol's defaults unless a model says otherwise. For Chat Completions the settings are `reasoningField`, `maxTokensField`, `seedField`, `streamOptions`, `forcesToolsOnlyWithoutReasoning`, `audioAddress`, `verboseTranscription`, `pdfPart` and `audioPart`, where `verboseTranscription` is for a host that reports the length of a recording only in a `verbose_json` answer, which a transcription then asks for; for Gemini, `thinkingBudget`, for a model that reads how deeply to think as a token budget rather than a thinking level. A model's own `hostSettings` replace the provider's whole set rather than adding to it. A setting whose name ends in `Address` or `Url` is an https address, as `defaultBaseUrl` is. |
| `keyFields` | The names of the values a key for the provider must come with. |
| `fieldPatterns` | The pattern each of those values must match. |
| `enabled` | Whether routing reaches the provider. |

## Put a model on it

```json
PUT /providers/hostly/models/Acme/acme-1
{
  "providerModelId": "acme/acme-1",
  "contextLength": 128000,
  "quantization": "fp8",
  "enabled": true,
  "operations": [
    {
      "operation": "Chat",
      "protocol": "ChatCompletions",
      "cost": { "promptTokens": 0.5, "completionTokens": 1.5 },
      "compatibility": { "toolUse": true, "contentTypes": ["image/png"] },
      "verifiesKeys": true
    }
  ]
}
```

| Field | Notes |
|---|---|
| `providerModelId` | The provider's own identifier for the model when it differs from the registered model name. |
| `baseUrl` · `authentication` · `hostSettings` | Where and how the model is reached when that differs from the provider's defaults. |
| `contextLength` · `quantization` | The provider's context cap and the precision it serves the model at. |
| `enabled` | Whether routing reaches the model on this provider. |
| `operations` | One for each operation the provider serves the model for — `Chat`, `Decision`, `Transcribe` or `Ocr` — in a protocol this deployment speaks: `ChatCompletions`, `OpenAI`, `Anthropic`, `Gemini` or `TypeSafe`. `cost` is per million tokens (`promptTokens`, `completionTokens`, `thoughtTokens`, with `cacheReadMultiplier` and `cacheWriteMultiplier` as multiples of `promptTokens`), and for an operation priced by the unit, `perUnit`: `{ "unit": "page", "price": 0.002 }` for an OCR model priced by the page or `{ "unit": "minute", "price": 0.0015 }` for a transcription model priced by the minute, `price` being US dollars for one unit. The provider list answers each operation's `cost` in the same shape. `compatibility` is what the operation can be handed, as the catalog's `capabilities` shows it. `verifiesKeys` marks the operation a caller's key for the provider is tried against before it is saved. |
