Attach a repository to a tenant (idempotent).
const url = 'https://shiftagent.example.com/tenants/example/repositories/example';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"is_default":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://shiftagent.example.com/tenants/example/repositories/example \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "is_default": true }'Idempotent attach: 201 on first attachment, 200 when the
attachment already existed (body fields merged — provided → replaced,
omitted → unchanged, null → cleared).
is_default: truealso setstenant.default_repository_id(and clears the flag from any previous default — one default at a time).branch_overridereads a different branch of the same repository for this tenant only.
The body is optional; a bare PUT attaches with defaults. This is
cold-path step 2: attach the registry repository as the tenant
default right after the tenant upsert returns 201.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Internal tenant ID.
Internal repository ID.
Request Body
Section titled “Request Body ”Optional body for attachTenantRepository. Merge semantics: provided → replaced, omitted → unchanged, null → cleared.
object
Make this the tenant default (sets tenant.default_repository_id; clears the previous default’s flag).
Read this branch for the tenant; null clears.
Examples
Cold-path attach as tenant default
{ "is_default": true}Responses
Section titled “ Responses ”Attachment already existed — fields merged.
A repository attached to a tenant. Addressed by the composite path /tenants/{tenant_id}/repositories/{repository_id} — no separate ID. Embeds the repository for convenience.
object
Whether this is the tenant default (⇔ tenant.default_repository_id). At most one per tenant.
Branch read for this tenant instead of the registry branch.
The attached repository, embedded.
object
Unique across the registry.
Git remote URL.
Branch scanned for skills (tenant attachments may override).
Git hosting flavor (drives auth mechanics).
Vault credential used to access the repository. Secret material is never readable — pre-authenticated at registration.
Skill-discovery sync state of a repository.
object
pending — not yet scanned (or invalidated by an update); syncing — scan in flight; ready — skill catalog current; error — last scan failed (see error).
Completion time of the last successful scan.
Human-readable failure reason when state is error.
Number of skills currently cataloged.
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
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
Example
{ "object": "repository_attachment", "repository": { "object": "repository", "branch": "main", "provider": "github", "sync": { "state": "pending" } }}Repository attached to the tenant.
A repository attached to a tenant. Addressed by the composite path /tenants/{tenant_id}/repositories/{repository_id} — no separate ID. Embeds the repository for convenience.
object
Whether this is the tenant default (⇔ tenant.default_repository_id). At most one per tenant.
Branch read for this tenant instead of the registry branch.
The attached repository, embedded.
object
Unique across the registry.
Git remote URL.
Branch scanned for skills (tenant attachments may override).
Git hosting flavor (drives auth mechanics).
Vault credential used to access the repository. Secret material is never readable — pre-authenticated at registration.
Skill-discovery sync state of a repository.
object
pending — not yet scanned (or invalidated by an update); syncing — scan in flight; ready — skill catalog current; error — last scan failed (see error).
Completion time of the last successful scan.
Human-readable failure reason when state is error.
Number of skills currently cataloged.
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
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
RFC 3339 / ISO 8601 timestamp, UTC.
Examples
Attached as tenant default
{ "object": "repository_attachment", "tenant_id": "tnt_01hzx8acme001", "repository_id": "rep_01hzx8fieldops", "is_default": true, "branch_override": null, "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.
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
Problem type URI (registry slug).
Short, human-readable summary of the problem type.
HTTP status code.
Human-readable explanation specific to this occurrence.
URI reference identifying this occurrence.
Correlation ID for support and log lookup.
On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).
On validation-error, field-level details.
object
JSON pointer to the offending field.
What failed.
Examples
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).
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
Problem type URI (registry slug).
Short, human-readable summary of the problem type.
HTTP status code.
Human-readable explanation specific to this occurrence.
URI reference identifying this occurrence.
Correlation ID for support and log lookup.
On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).
On validation-error, field-level details.
object
JSON pointer to the offending field.
What failed.
Examples
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) or role-required (user has multiple roles and no role_id was given).
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
Problem type URI (registry slug).
Short, human-readable summary of the problem type.
HTTP status code.
Human-readable explanation specific to this occurrence.
URI reference identifying this occurrence.
Correlation ID for support and log lookup.
On name-conflict, external-id-conflict, and resource-in-use: the ID of the existing/depended-on resource — fetch it and continue (replay recovery).
On validation-error, field-level details.
object
JSON pointer to the offending field.
What failed.
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 effective repository." } ], "request_id": "req_01hzx8val001"}Ambiguous role at conversation creation
{ "type": "https://shiftagent.example.com/problems/role-required", "title": "Role required", "status": 422, "detail": "User usr_01hzx8jane001 holds 2 roles; pass role_id explicitly.", "request_id": "req_01hzx8role01"}