Veto/docs

Organizations API

CRUD endpoints for organizations — the top-level scope for projects, policies, and API keys.

Organizations are the top-level grouping in Veto. Every project, policy, tool, and API key belongs to an organization. Each organization has an owner (the user who created it) and a billing tier.

Most endpoints accept both JWT and API key auth. Mutating operations (create, update, delete) require JWT user authentication and cannot be performed with API keys.

GET /v1/organizations

List organizations accessible to the authenticated user. API key auth returns only the organization the key belongs to.

Headers

HeaderRequiredDescription
X-Veto-API-Key or AuthorizationYesAPI key or Bearer JWT

Response

{
  "data": [
    {
      "_id": "org_abc123",
      "name": "Acme Corp",
      "slug": "acme-corp",
      "ownerId": "user_xyz789",
      "tier": "team",
      "billingPeriodStart": "2025-01-01T00:00:00Z",
      "createdAt": "2025-01-15T10:00:00Z",
      "updatedAt": "2025-01-20T14:30:00Z"
    }
  ]
}

Example

curl https://api.veto.so/v1/organizations \
  -H "Authorization: Bearer $JWT_TOKEN"

POST /v1/organizations

Create a new organization. Requires JWT auth (API keys cannot create organizations).

Headers

HeaderRequiredDescription
AuthorizationYesBearer JWT
Content-TypeYesapplication/json

Body

{
  "name": "Acme Corp",
  "slug": "acme-corp"
}
FieldTypeRequiredDescription
namestringYesDisplay name (1-100 chars)
slugstringYesURL-safe identifier (1-100 chars, lowercase alphanumeric and hyphens only)

Response (201)

{
  "_id": "org_abc123",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "ownerId": "user_xyz789",
  "tier": "free",
  "billingPeriodStart": null,
  "createdAt": "2025-01-20T14:30:00Z",
  "updatedAt": null
}

Errors

StatusCodeDescription
403authorization_errorAPI keys cannot create organizations
409slug_takenAn organization with this slug already exists

Example

curl -X POST https://api.veto.so/v1/organizations \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "slug": "acme-corp"
  }'

GET /v1/organizations/:id

Get an organization by ID.

Headers

HeaderRequiredDescription
X-Veto-API-Key or AuthorizationYesAPI key or Bearer JWT

Path parameters

ParameterTypeDescription
idstringOrganization ID

Response

{
  "_id": "org_abc123",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "ownerId": "user_xyz789",
  "tier": "team",
  "billingPeriodStart": "2025-01-01T00:00:00Z",
  "createdAt": "2025-01-15T10:00:00Z",
  "updatedAt": "2025-01-20T14:30:00Z"
}

Errors

StatusCodeDescription
403authorization_errorNot a member of this organization
404not_foundOrganization does not exist

Example

curl https://api.veto.so/v1/organizations/org_abc123 \
  -H "Authorization: Bearer $JWT_TOKEN"

GET /v1/organizations/slug/:slug

Look up an organization by slug.

Headers

HeaderRequiredDescription
X-Veto-API-Key or AuthorizationYesAPI key or Bearer JWT

Path parameters

ParameterTypeDescription
slugstringOrganization slug

Response

Same shape as GET /v1/organizations/:id.

Errors

StatusCodeDescription
403authorization_errorNot a member of this organization
404not_foundNo organization with this slug

Example

curl https://api.veto.so/v1/organizations/slug/acme-corp \
  -H "Authorization: Bearer $JWT_TOKEN"

PUT /v1/organizations/:id

Update an organization. Requires JWT auth. All body fields are optional (partial update).

Headers

HeaderRequiredDescription
AuthorizationYesBearer JWT
Content-TypeYesapplication/json

Path parameters

ParameterTypeDescription
idstringOrganization ID

Body

{
  "name": "Acme Industries",
  "slug": "acme-industries"
}
FieldTypeRequiredDescription
namestringNoNew display name (1-100 chars)
slugstringNoNew URL-safe slug (1-100 chars, lowercase alphanumeric and hyphens only)

Response

{
  "_id": "org_abc123",
  "name": "Acme Industries",
  "slug": "acme-industries",
  "ownerId": "user_xyz789",
  "tier": "team",
  "billingPeriodStart": "2025-01-01T00:00:00Z",
  "createdAt": "2025-01-15T10:00:00Z",
  "updatedAt": "2025-01-21T09:00:00Z"
}

Errors

StatusCodeDescription
403authorization_errorAPI keys cannot update organizations, or not a member
404not_foundOrganization does not exist
409slug_takenSlug is already in use by another organization

Example

curl -X PUT https://api.veto.so/v1/organizations/org_abc123 \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Acme Industries" }'

DELETE /v1/organizations/:id

Delete an organization and all associated data. Requires JWT auth. This is irreversible.

Headers

HeaderRequiredDescription
AuthorizationYesBearer JWT

Path parameters

ParameterTypeDescription
idstringOrganization ID

Response

{
  "success": true
}

Errors

StatusCodeDescription
403authorization_errorAPI keys cannot delete organizations, or not a member
404not_foundOrganization does not exist

Example

curl -X DELETE https://api.veto.so/v1/organizations/org_abc123 \
  -H "Authorization: Bearer $JWT_TOKEN"

Organization response fields

FieldTypeDescription
_idstringOrganization ID
namestringDisplay name
slugstringURL-safe identifier
ownerIdstringID of the user who owns this org
tier"free" | "team" | "business" | "enterprise"Billing tier
billingPeriodStartstring?ISO 8601 start of current billing period
createdAtstringISO 8601 creation timestamp
updatedAtstring?ISO 8601 last update timestamp