# Resources, integrations, and bindings API

> Create and control tenant Resources, inspect contracts, and manage scoped Resource or Credential assignments.

## Resources {#resources}

| Method | Path | Purpose |
| --- | --- | --- |
| `GET` / `POST` | `/v1/namespaces/:namespace/resources` | List `?kind=...` or create a configured Resource |
| `GET` | `/v1/namespaces/:namespace/gateway-catalog` | List Gateway packages visible to the tenant |
| `POST` | `/v1/namespaces/:namespace/gateways/install` | Install a Gateway package with configuration and Credential bindings |
| `POST` | `/v1/namespaces/:namespace/models` | Create a tenant-billed Model from an advertised or manual Gateway offer |
| `GET` / `DELETE` | `/v1/namespaces/:namespace/resources/:kind/:id` | Read or delete a tenant-managed Resource |
| `GET` | `/v1/namespaces/:namespace/resources/:kind/:id/control` | Read control head |
| `POST` | `/v1/namespaces/:namespace/resources/:kind/:id/enable` | Enable with `eventId` and optional reason |
| `POST` | `/v1/namespaces/:namespace/resources/:kind/:id/disable` | Disable with `eventId` and optional reason |

Platform catalog Resources are merged into list/read responses but tenants cannot mutate or delete them.

`POST .../resources` does not accept `kind: "policy"`. Public Policies are deterministic executable packages deployed through the common deployment API. A Policy package's `constal.policy.json` supplies one required `target` with a `resourceKind` and normalized label selector; the Registry materializes applicable Resource edges when the package is promoted.

`POST .../models` accepts `{ id, gateway, offer }`. Use `offer: { kind: "advertised", modelId }` to reload and pin immutable package metadata, or `offer: { kind: "manual", model }` when the Gateway has no static catalog. The selected Gateway must be tenant-billed and implement the model-completion capability. Admission stores displayed provider pricing separately from accounting and creates no Constal platform charge. See [Add and manage Models](/docs/resources/models.md).

### UI publication {#ui-publication}

Publish a UI with `POST /v1/namespaces/:namespace/resources` and `kind: "ui"`; there is no separate UI deployment endpoint. The body supplies `id`, `version`, `displayName`, `description`, `policies`, exact `target.channel` and `target.agent` CRN/hash pairs, `access`, `execution`, `limits`, and `expectedCurrentHash`.

`source` is either the immutable platform chat template or a pinned CAS bundle:

```json
{ "kind": "template", "template": "chat", "version": "1" }
```

```json
{
  "kind": "bundle",
  "artifact": {
    "cas": { "crn": "CAS_CRN", "hash": "CAS_RESOURCE_HASH" },
    "ref": "BUNDLE_HASH",
    "manifestHash": "MANIFEST_HASH",
    "format": "constal.ui.v1"
  }
}
```

Creation uses `expectedCurrentHash: null`. Publishing another immutable revision of the same UI requires the exact current hash. A successful response includes the Resource, generated `routeId`, and stable URL. Read, history, enable, disable, and delete continue through the generic Resource endpoints. See [Build and publish Dynamic UIs](/docs/resources/dynamic-uis.md) for the complete bundle, CAS, CLI, and durable-state workflow.

A UI declared in a `constal.agent.json` `ui` block is created and re-pinned by `constal deploy` itself, as a `ui` Resource whose `target.agent` is the Agent revision that deployment produced; standalone creation through this endpoint is unchanged. See [Deploy an Agent with a UI](/docs/agents/deploy.md#ui).

## Resource contracts {#implementations}

| Method | Path | Purpose |
| --- | --- | --- |
| `GET` / `POST` | `/v1/namespaces/:namespace/resource-contracts` | List or publish an immutable Resource contract |
| `GET` | `/v1/namespaces/:namespace/resource-contracts/:id/:version?hash=...` | Read one exact contract |

Resource contracts describe the operations, schemas, effects, and capabilities an integration must provide. Use the Console workflow for installing or configuring an integration rather than depending on implementation internals.

## Scoped assignments {#bindings}

| Method | Path | Purpose |
| --- | --- | --- |
| `GET` / `POST` | `/v1/namespaces/:namespace/bindings` | List visible assignments or create one |
| `GET` / `DELETE` | `/v1/namespaces/:namespace/bindings/:id` | Read or delete one assignment head |
| `POST` | `/v1/namespaces/:namespace/bindings/:id/promote` | Promote to a new target when `expectedHeadSeq` still matches |
| `POST` | `/v1/namespaces/:namespace/bindings/:id/enable`, `/disable`, `/revoke` | Apply an idempotent lifecycle control |
| `GET` | `/v1/namespaces/:namespace/integrations[/:id]` | Read owner-filtered integration projections |

Creation and promotion declare the logical key, owner, target class, exact target CRN/hash, a Resource contract or explicit `null` for a Credential, and a stable event identity and reason. Promotion also supplies the observed `expectedHeadSeq`; the ChangePlan freezes the current revision so a changed head fails before mutation. Lifecycle controls advance a separate control sequence on the logical Binding. Customer/principal callers can see only assignments within their accepted ownership boundary. See [Scoped bindings](/docs/credentials/scoped-bindings) for resolution semantics.
