# Provider API

The OpenAPI 3.1 document is the full description, including schemas:

https://router.inference.ai.exchange/v1/openapi.json

## `GET /v1/provider/jobs`

List the settled jobs of this provider, oldest first.

A row has the earnings, the fee, the charge and credit of the buyer, the meters
and the measured latency of one job. A job appears five minutes after it
settles and does not change after that. Send the `next_cursor` of the last read
to get only new jobs.

## `GET /v1/provider/model-registry`

## `GET /v1/provider/models`

List every deployment that this provider registered, in every status.

Use it to see whether a registration is unlisted, listed or suspended and why,
and whether it is paused. The `listed` frame of the session says which
deployments can be quoted now. Each row holds the last refused quote of the
deployment until a later quote rests, so a client that does not log
`quote_reject` frames can still read why.

## `POST /v1/provider/models`

Register a deployment and resolve its approved identity.

The exchange checks the claimed model name, creator, kind and base model. It
leaves an unknown name or a metadata conflict unlinked. An operator must admit
a new deployment. Registration keeps the unlists, pauses and suspensions of an
operator. A change of metadata voids the earlier admission before the exchange
resolves the new claim.

## `POST /v1/provider/models/{id}/pause`

Pause a deployment and remove its offer from the book.

Use it when you stop serving a deployment. The offer leaves the book at once
and cannot win an award. The registration and the decision of the operator
stay. Registering again does not resume the deployment. Resume it with
`POST /v1/provider/models/{id}/resume`.

## `POST /v1/provider/models/{id}/resume`

Resume a deployment that this provider paused.

Use it when a model left the rate card and came back. The offer can rest on the
book again. A suspended deployment stays unchanged, because an operator barred
it. A deployment that was never paused also stays unchanged, so a new model
still waits for an operator to list it.

## `GET /v1/provider/ws`

Open the session of a bidding agent, over a WebSocket.

Send a `login` frame first, with the slug of the provider, its credential and
the URL where the exchange sends jobs. Any other first frame closes the socket.
The exchange replies with `login_ack` and a `listed` frame. `listed` names each
deployment that the provider can quote. The exchange sends it again when an
operator changes the list.

Then send one `quote` frame for each listed deployment. The exchange replies
with `quote_ack` or `quote_reject`. A quote is firm for `valid_for_ms`. It
leaves the book when that time ends, when you withdraw it or when the socket
closes. Send a new quote when the price changes. `revision` must increase
within one session.

Jobs arrive separately. The exchange sends a `POST` of a `DispatchRequest` to
the `dispatch_url` of the login, with the award id in the `idempotency-key`
header. The agent answers with newline-delimited `DispatchEvent` frames. On
this socket, an `award_notice` comes before each job and a `settlement_notice`
after it. The agent sends `ProviderMessage` frames and the exchange sends
`ExchangeMessage` frames.

A second login for the same provider replaces the first and removes its
offers. This is how a reconnect works. A login with the `handover` capability
does not remove them. The first session keeps its offers until the second
quotes each one again, at any revision. Then the first gets `superseded` and
closes. An award on an offer of the first session goes to that session and its
`dispatch_url`. So a new agent process can replace an old one with no gap in
the book.

A login with the `notice_ack` capability acknowledges each `award_notice` and
`settlement_notice` with a `notice_ack` frame. The exchange keeps each notice
with no ack for 15 minutes and sends it again at the next login with
`notice_ack`. A notice can arrive more than once.

When the exchange ends a session, the close frame has a code:

- 1012: the exchange process stops.
- 4000: a login without `handover` replaced the session.
- 4001: superseded.
- 4002: no frame before the heartbeat timeout.
- 4003: the agent did not read its control messages.
- 4004: the key was revoked.
- 4005: the provider is not admitted.
- 4006: the jurisdiction does not allow trade.

After 4004, 4005 or 4006 a login fails, so wait before the next one. A socket
that ends with no close frame is a network fault or a crash.
