---
title: "Assign Site Integration"
method: PUT
path: "/sites/{site_id}/integrations/{integration_id}"
tags: ["integrations"]
---

# Assign Site Integration

`PUT /sites/{site_id}/integrations/{integration_id}`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/sites/{site_id}/integrations/{integration_id}`
- Auth: HTTP bearer

Assign an existing connection of the site's client to the site.

Idempotent (200, `already_assigned: true`) for the same pair. 404 for a
connection of another client (out-of-tenant is not found). 409 when the site
already uses a DIFFERENT connection of that provider, or has live cameras
still streaming through one.

## Path parameters

- `site_id` string, required
- `integration_id` string, required

## Response `200`

Successful Response

- AssignSiteIntegrationResponse
  - `site_id` string, uuid, required: The site the connection is now assigned to.
  - `integration` SiteIntegrationResponse, required: One cloud-VMS connection. There is deliberately NO api_key field and NO secret_arn field. The key never leaves Secrets Manager, and the ARN is an internal handle with no client-facing use (the same omission as NvrResponse / the speaker responses). Because FastAPI serializes through this model, a field that somehow appeared in the service dict would be dropped here rather than reaching a client — a second layer under to_dict_complete's omission, and the property the router leak test pins.
    - `id` string, uuid, required: The integration record ID.
    - `parent_id` string, uuid, required: The client this connection belongs to. The credential is client-level; WHICH SITES it serves is `site_ids`.
    - `provider` 'verkada' | 'turing' | 'avertx', required
    - `label` string, required: Operator-facing name for this connection.
    - `external_org_id` string, nullable: Provider organization id (non-secret), for display.
    - `command_short_name` string, nullable: The vendor console's organization short name (the subdomain in https://<short-name>.command.verkada.com/...). Owner-entered, never fetched from the provider, and used only to build an operator's deep link. A Verkada concept: providers whose console has no such deep link leave it null.
    - `status` 'active' | 'error', required
    - `last_verified_at` string, date-time, nullable: When the connection last tested successfully.
    - `last_error` string, nullable: Most recent connection-test failure, sanitized and truncated. Never contains a credential.
    - `site_ids` string[]: The live sites this connection is assigned to, ordered by id. Empty means UNASSIGNED: the connection is listed and manageable but no site uses it yet. Absent from payloads of older servers (read as empty).
    - `created_at` string, date-time, required: When the connection was created.
    - `updated_at` string, date-time, nullable: When the connection was last modified.
  - `already_assigned` boolean, required: True when the connection was already assigned to this site and nothing was written (the call is idempotent).

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/verdun/apis/verdun-api.md) - [All operations](https://skmtc.dev/verdun/apis/verdun-api/llms.txt) - [OpenAPI document](https://skmtc.dev/verdun/apis/verdun-api/revisions/35a2a6ebedda?raw)
