Skip to content

Assign (or replace) the tenant's repository.

PUT
/tenants/{tenant_id}/repository
curl --request PUT \
--url https://shiftagent.example.com/tenants/example/repository \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "repository_id": "rep_01hzx8fieldops" }'

Idempotent assignment of the tenant’s single repository: 201 on first assignment, 200 when an assignment already existed (fields merged — provided → replaced, omitted → unchanged, null → cleared; pointing at a different repository_id replaces the assignment).

This is cold-path step 2: assign the registry repository right after the tenant upsert returns 201. A tenant has at most one repository; roles narrow which of its skills are usable (skill_access), and conversations/messages inherit it — there are no per-role, per-user, per-conversation, or per-message repository overrides.

branch_override reads a different branch of the same repository for this tenant only.

tenant_id
required
string
/^tnt_[A-Za-z0-9]+$/

Internal tenant ID.

Media type application/json

Body for assignTenantRepository. Merge semantics: provided → replaced, omitted → unchanged, null → cleared.

object
repository_id
required

The registry repository to assign. Pointing at a different repository replaces the assignment.

string
/^rep_[A-Za-z0-9]+$/
branch_override

Read this branch for the tenant; null clears.

string | null
Examples
Example assign

Cold-path assignment

{
"repository_id": "rep_01hzx8fieldops"
}

Assignment already existed — fields merged/replaced.

Media type application/json

A tenant’s repository assignment (each tenant has at most one). Addressed by the singular path /tenants/{tenant_id}/repository — no separate ID. Embeds the repository for convenience. inherited: true marks an assignment resolved from the nearest ancestor tenant.

object
object
required
string
Allowed value: tenant.repository
tenant_id
required

The tenant addressed (not the ancestor when inherited).

string
/^tnt_[A-Za-z0-9]+$/
repository_id
required
string
/^rep_[A-Za-z0-9]+$/
branch_override
required

Branch read for this tenant instead of the registry branch.

string | null
inherited
required

True when the tenant has no assignment of its own and this is the nearest ancestor’s.

boolean
repository
required

The assigned repository, embedded.

object
object
required
string
Allowed value: repository
id
required
string
/^rep_[A-Za-z0-9]+$/
name
required

Unique across the registry.

string
<= 255 characters
repo_url
required

Git remote URL.

string format: uri
branch
required

Branch scanned for skills (tenant attachments may override).

string
default: main
provider
required

Git hosting flavor (drives auth mechanics).

string
default: generic
Allowed values: github gitlab bitbucket azure_devops generic
credential_id
required

Vault credential used to access the repository. Secret material is never readable — pre-authenticated at registration.

string | null
/^crd_[A-Za-z0-9]+$/
sync
required

Skill-discovery sync state of a repository.

object
state
required

pending — not yet scanned (or invalidated by an update); syncing — scan in flight; ready — skill catalog current; error — last scan failed (see error).

string
Allowed values: pending syncing ready error
last_synced_at
required

Completion time of the last successful scan.

string | null format: date-time
error
required

Human-readable failure reason when state is error.

string | null
skill_count
required

Number of skills currently cataloged.

integer
metadata
required

Free-form string key–value map for host/adapter bookkeeping (e.g. a host-side reference ID). Max 50 keys; values max 500 chars. Replaced wholesale when provided in updates.

object
<= 50 properties
key
additional properties
string
<= 500 characters
created_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
updated_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
created_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
updated_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
Example
{
"object": "tenant.repository",
"repository": {
"object": "repository",
"branch": "main",
"provider": "github",
"sync": {
"state": "pending"
}
}
}

Repository assigned to the tenant.

Media type application/json

A tenant’s repository assignment (each tenant has at most one). Addressed by the singular path /tenants/{tenant_id}/repository — no separate ID. Embeds the repository for convenience. inherited: true marks an assignment resolved from the nearest ancestor tenant.

object
object
required
string
Allowed value: tenant.repository
tenant_id
required

The tenant addressed (not the ancestor when inherited).

string
/^tnt_[A-Za-z0-9]+$/
repository_id
required
string
/^rep_[A-Za-z0-9]+$/
branch_override
required

Branch read for this tenant instead of the registry branch.

string | null
inherited
required

True when the tenant has no assignment of its own and this is the nearest ancestor’s.

boolean
repository
required

The assigned repository, embedded.

object
object
required
string
Allowed value: repository
id
required
string
/^rep_[A-Za-z0-9]+$/
name
required

Unique across the registry.

string
<= 255 characters
repo_url
required

Git remote URL.

string format: uri
branch
required

Branch scanned for skills (tenant attachments may override).

string
default: main
provider
required

Git hosting flavor (drives auth mechanics).

string
default: generic
Allowed values: github gitlab bitbucket azure_devops generic
credential_id
required

Vault credential used to access the repository. Secret material is never readable — pre-authenticated at registration.

string | null
/^crd_[A-Za-z0-9]+$/
sync
required

Skill-discovery sync state of a repository.

object
state
required

pending — not yet scanned (or invalidated by an update); syncing — scan in flight; ready — skill catalog current; error — last scan failed (see error).

string
Allowed values: pending syncing ready error
last_synced_at
required

Completion time of the last successful scan.

string | null format: date-time
error
required

Human-readable failure reason when state is error.

string | null
skill_count
required

Number of skills currently cataloged.

integer
metadata
required

Free-form string key–value map for host/adapter bookkeeping (e.g. a host-side reference ID). Max 50 keys; values max 500 chars. Replaced wholesale when provided in updates.

object
<= 50 properties
key
additional properties
string
<= 500 characters
created_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
updated_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
created_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
updated_at
required

RFC 3339 / ISO 8601 timestamp, UTC.

string format: date-time
Examples
Example assigned

Assigned

{
"object": "tenant.repository",
"tenant_id": "tnt_01hzx8acme001",
"repository_id": "rep_01hzx8fieldops",
"branch_override": null,
"inherited": false,
"repository": {
"object": "repository",
"id": "rep_01hzx8fieldops",
"name": "field-ops",
"repo_url": "https://git.example.com/agent-skills/field-ops.git",
"branch": "main",
"provider": "generic",
"credential_id": "crd_01hzx8gitmain",
"sync": {
"state": "ready",
"last_synced_at": "2026-07-02T09:33:00Z",
"error": null
},
"skill_count": 5,
"metadata": {},
"created_at": "2026-07-02T09:31:00Z",
"updated_at": "2026-07-02T09:33:00Z"
},
"created_at": "2026-07-02T09:34:00Z",
"updated_at": "2026-07-02T09:34:00Z"
}

Missing or invalid credentials — no bearer token, an unknown/revoked sk_int_ key, or an expired platform JWT.

Media type application/problem+json

RFC 9457 problem+json error envelope. type is a URI under https://shiftagent.example.com/problems/{slug} (deployment host substituted); see the API-level problem registry for every slug.

object
type
required

Problem type URI (registry slug).

string format: uri-reference
title
required

Short, human-readable summary of the problem type.

string
status
required

HTTP status code.

integer format: int32
detail

Human-readable explanation specific to this occurrence.

string
instance

URI reference identifying this occurrence.

string format: uri-reference
request_id

Correlation ID for support and log lookup.

string
conflicting_resource_id

On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).

string
errors

On validation-error, field-level details.

Array<object>
object
pointer
required

JSON pointer to the offending field.

string
message
required

What failed.

string
Examples
Example unauthorized

Missing or invalid bearer token

{
"type": "https://shiftagent.example.com/problems/insufficient-scope",
"title": "Unauthorized",
"status": 401,
"detail": "Provide a valid sk_int_ service key or platform JWT.",
"request_id": "req_01hzx8auth001"
}

Not found — the resource does not exist, was deprovisioned, or lies outside the integration key’s subtree (indistinguishable by design).

Media type application/problem+json

RFC 9457 problem+json error envelope. type is a URI under https://shiftagent.example.com/problems/{slug} (deployment host substituted); see the API-level problem registry for every slug.

object
type
required

Problem type URI (registry slug).

string format: uri-reference
title
required

Short, human-readable summary of the problem type.

string
status
required

HTTP status code.

integer format: int32
detail

Human-readable explanation specific to this occurrence.

string
instance

URI reference identifying this occurrence.

string format: uri-reference
request_id

Correlation ID for support and log lookup.

string
conflicting_resource_id

On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).

string
errors

On validation-error, field-level details.

Array<object>
object
pointer
required

JSON pointer to the offending field.

string
message
required

What failed.

string
Examples
Example not_found

Unknown resource

{
"type": "https://shiftagent.example.com/problems/not-found",
"title": "Not found",
"status": 404,
"detail": "No tenant with external_id acme:tenant:999999.",
"request_id": "req_01hzx8nf001"
}

Unprocessable — validation-error (schema/semantic validation failed; errors[] lists JSON-pointer details), role-required (the user has no role assigned, so no conversation context can resolve), or missing-secret (a referenced alias is vaulted at no scope).

Media type application/problem+json

RFC 9457 problem+json error envelope. type is a URI under https://shiftagent.example.com/problems/{slug} (deployment host substituted); see the API-level problem registry for every slug.

object
type
required

Problem type URI (registry slug).

string format: uri-reference
title
required

Short, human-readable summary of the problem type.

string
status
required

HTTP status code.

integer format: int32
detail

Human-readable explanation specific to this occurrence.

string
instance

URI reference identifying this occurrence.

string format: uri-reference
request_id

Correlation ID for support and log lookup.

string
conflicting_resource_id

On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).

string
errors

On validation-error, field-level details.

Array<object>
object
pointer
required

JSON pointer to the offending field.

string
message
required

What failed.

string
Examples

Field-level validation failure

{
"type": "https://shiftagent.example.com/problems/validation-error",
"title": "Validation error",
"status": 422,
"detail": "One or more fields failed validation.",
"errors": [
{
"pointer": "/skill_access/skill_ids/0",
"message": "skl_01hzx8unknown does not belong to the tenant's repository."
}
],
"request_id": "req_01hzx8val001"
}