Skip to content

Organizations

All routes are under /api/v1/organizations. {orgID} accepts a UUID or a slug.

Terminal window
export API=https://cavsnode.com/api/v1
export ORG=acme-ai
export H="Authorization: Bearer $CAVS_TOKEN"

Token-only credentials can reach the read endpoints via org:read (or repo:read) and the usage endpoints via usage:read. Members, tokens, storage connections, billing and audit are not reachable by any token scope — they need a session-authenticated role. See Roles & permissions.

Every organization the caller belongs to.

Terminal window
curl -sS -X POST "$API/organizations" -H "$H" -H "Content-Type: application/json" \
-d '{"name": "Acme AI", "slug": "acme-ai"}'

The creator becomes OWNER. The slug must be unique platform-wide; omit it and it’s derived from the name.

Endpoint Permission
GET /organizations/{orgID} organization.read
PATCH /organizations/{orgID} organization.update
DELETE /organizations/{orgID} organization.deleteOWNER only
Terminal window
curl -sS "$API/organizations/$ORG" -H "$H"
curl -sS -X PATCH "$API/organizations/$ORG" \
-H "$H" -H "Content-Type: application/json" \
-d '{"name": "Acme AI Labs"}'
Endpoint Permission
GET /organizations/{orgID}/members members.read
PATCH /organizations/{orgID}/members/{userID} members.remove
DELETE /organizations/{orgID}/members/{userID} members.remove
POST /organizations/{orgID}/leave organization.read
Terminal window
curl -sS "$API/organizations/$ORG/members" -H "$H"
# Change a role
curl -sS -X PATCH "$API/organizations/$ORG/members/$USER_ID" \
-H "$H" -H "Content-Type: application/json" -d '{"role": "ADMIN"}'
# Remove
curl -sS -X DELETE "$API/organizations/$ORG/members/$USER_ID" -H "$H"
# Leave yourself
curl -sS -X POST "$API/organizations/$ORG/leave" -H "$H"

Roles: OWNER, ADMIN, DEVELOPER, VIEWER, BILLING. A sole OWNER must transfer ownership before leaving.

Endpoint Permission
GET /organizations/{orgID}/invitations members.read
POST /organizations/{orgID}/invitations members.invite
POST /organizations/{orgID}/invitations/{invID}/link members.invite
DELETE /organizations/{orgID}/invitations/{invID} members.invite
Terminal window
curl -sS -X POST "$API/organizations/$ORG/invitations" \
-H "$H" -H "Content-Type: application/json" \
-d '{"email": "[email protected]", "role": "DEVELOPER"}'

For inviting someone to a single repository without org membership, see repository invitations.

Endpoint Permission
GET /organizations/{orgID}/usage usage.read
GET /organizations/{orgID}/usage/series usage.read
GET /organizations/{orgID}/dashboard usage.read
GET /organizations/{orgID}/activity repositories.read
GET /organizations/{orgID}/recommendations usage.read
Terminal window
curl -sS "$API/organizations/$ORG/usage" -H "$H"
curl -sS "$API/organizations/$ORG/usage/series?days=90" -H "$H"
curl -sS "$API/organizations/$ORG/dashboard" -H "$H"
curl -sS "$API/organizations/$ORG/activity?limit=100&repo=$REPO" -H "$H"
curl -sS "$API/organizations/$ORG/recommendations" -H "$H"
Parameter Endpoint Range Default
days usage/series 1–365 90
limit activity 1–200 50
skip activity 0–10000 0
type, actor, repo activity all

usage splits managed from BYOS bytes, since only managed storage and egress are metered. dashboard is the aggregate the org overview renders: totals, counts, recent activity, forecast, plan limits. See Storage insights.

Every artifact across every repository. Permission: repositories.read.

Terminal window
curl -sS "$API/organizations/$ORG/artifacts?sort=size&limit=20" -H "$H"
curl -sS "$API/organizations/$ORG/artifacts?type=model&q=resnet" -H "$H"
curl -sS "$API/organizations/$ORG/artifacts?repo=$REPO&sort=downloads" -H "$H"
Parameter Values
repo a repository UUID
type model, dataset, media, archive, other
q name substring
sort recent (default), size, downloads, name
limit page size
before RFC 3339 cursor — recent sort only
{ "artifacts": [ ], "total": 1284, "next_before": "2026-07-20T11:04:02.117Z" }

Feed next_before back as before to page. An invalid repo or before gives 400.

Endpoint Permission
GET /organizations/{orgID}/storage-groups storage.read
POST /organizations/{orgID}/storage-groups storage.manage
GET /organizations/{orgID}/storage-groups/{groupID} storage.read
PATCH /organizations/{orgID}/storage-groups/{groupID} storage.manage
DELETE /organizations/{orgID}/storage-groups/{groupID} storage.manage
Terminal window
curl -sS -X POST "$API/organizations/$ORG/storage-groups" \
-H "$H" -H "Content-Type: application/json" \
-d '{"name": "Training data", "description": "Datasets and preprocessing outputs"}'

Deleting a group un-groups its repositories; it never deletes data. See Storage groups.

Endpoint Permission
GET /organizations/{orgID}/repositories repositories.read
POST /organizations/{orgID}/repositories repositories.create
Terminal window
# Resolve slugs to the UUIDs the repository routes need
curl -sS "$API/organizations/$ORG/repositories" -H "$H" \
| jq -r '.repositories[] | "\(.slug)\t\(.id)"'
curl -sS -X POST "$API/organizations/$ORG/repositories" \
-H "$H" -H "Content-Type: application/json" \
-d '{
"name": "Vision Models",
"slug": "vision-models",
"description": "Trained checkpoints",
"visibility": "PRIVATE",
"storage_mode": "managed"
}'
Field Values Default
name required
slug URL-safe, unique in the org derived from name
description free text empty
visibility PRIVATE, INTERNAL, PUBLIC PRIVATE
storage_mode managed, byos managed
storage_connection_id required when storage_mode is byos

Errors: 409 conflict on a duplicate slug, 402 quota_exceeded at the plan’s repository limit, 400 for an invalid visibility or a BYOS mode your plan doesn’t allow (or an unhealthy connection).

Documented separately because they’re administrative: