---
title: "Report a relay instance's manifest"
method: PUT
path: "/relays/instances/{instance_id}"
---

# Report a relay instance's manifest

`PUT /relays/instances/{instance_id}`

## Request

- Base URL: `https://api.endclose.com/v1`
- URL: `https://api.endclose.com/v1/relays/instances/{instance_id}`
- Auth: API key in header `X-API-KEY`

A running relay instance describing itself: host kind, engine version, the routes-document schema version it understands, where its configuration comes from, and the adapters and enrichments it has registered. Idempotent replace keyed by the environment the API key belongs to plus a host-chosen instance id (up to 128 characters; embedded hosts without a configured id use a random UUID per process). Send it on boot and on every heartbeat. End Close checks any document saved for the environment against the instances seen in the last 24 hours: every route `source` must be an adapter every live instance has, every `enrich:` an enrichment every live instance has registered (none at all while any live instance is the standard application), and no document feature newer than the oldest instance's `config_schema`. Instances unseen for 30 days are deleted. Nothing is required of a relay that never sends a manifest: authoring then falls back to the built-in adapters and no enrichments.

## Path parameters

- `instance_id` string, required

## Request body

- RelayInstanceManifest
  - `schema` 1, required: Manifest format version. Unknown values are rejected with 400.
  - `reason` string, required: Why the relay is checking in. One lowercase word: `boot`, `heartbeat`, `config_applied`, `error` and `shutdown` are the ones End Close knows about, and any other lowercase word is accepted and stored, so a new relay version is never blocked from checking in. Only `shutdown` carries meaning: it is recorded but does not refresh the instance's liveness, so an instance that says goodbye stops constraining what a document may name instead of counting as alive for another 24 hours. Send no other detail with it — extra keys are stored verbatim and never read, which is the wrong home for stack traces or metrics.
  - `host` 'application' | 'embedded', required: The shipped Docker image, or `createRelay()` embedded in the customer's own backend.
  - `engine_version` string, required: Semver of `@end-close/relay` in use.
  - `config_schema` integer, required: The routes-document schema version this engine understands. Version 1 is current. Gates which document features may be saved: nothing newer than the oldest reporting instance understands.
  - `config_source` 'remote' | 'local', required: `remote` fetches from End Close; `local` has routes supplied in code or by file. Informational.
  - `capabilities` object, required
    - `adapters` string[], required: Lowercase adapter slugs. Always includes the built-ins `payabli` and `generic_hmac`.
    - `enrichments` object: Registered enrichment functions keyed by lowercase snake_case name. Each value is a descriptor that may be empty; recognised keys are `description` (string) and `output` (`string` | `number` | `boolean`). Unknown keys are stored as sent.

## Response `204`

Manifest stored

## Other responses

- `400`: Malformed manifest; the message names the field
- `401`: Unauthorized — missing, invalid, or revoked API key
- `403`: Forbidden — the key is a run-scoped agent session key, not a relay key
- `413`: Body exceeds 64 KB

## Changes

- **2026-09-10** `7cb4a01bf0be`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/endclose/apis/end-close-api/changes/relays/instances/:instance_id/put.md)

---

[API](https://skmtc.dev/endclose/apis/end-close-api.md) - [All operations](https://skmtc.dev/endclose/apis/end-close-api/llms.txt) - [OpenAPI document](https://skmtc.dev/endclose/apis/end-close-api/revisions/dfe0fde00f12?raw)
