Tokens, webhooks & billing
Organization-scoped administrative endpoints.
export API=https://cavsnode.com/api/v1export ORG=acme-aiexport H="Authorization: Bearer $CAVS_TOKEN"export J="Content-Type: application/json"API tokens
Section titled “API tokens”| Endpoint | Permission | |
|---|---|---|
| GET | /organizations/{orgID}/tokens |
tokens.create |
| POST | /organizations/{orgID}/tokens |
tokens.create |
| DELETE | /organizations/{orgID}/tokens/{tokenID} |
tokens.revoke |
curl -sS "$API/organizations/$ORG/tokens" -H "$H"
curl -sS -X POST "$API/organizations/$ORG/tokens" -H "$H" -H "$J" \ -d '{ "name": "github-actions/vision-build", "kind": "CI", "scopes": ["repo:write"], "expires_in_days": 90 }'
curl -sS -X DELETE "$API/organizations/$ORG/tokens/$TOKEN_ID" -H "$H"| Field | Values | Notes |
|---|---|---|
name |
required | Say where it lives — that’s what you’ll read when deciding what to revoke |
kind |
PAT (default), REPO, CI |
Determines the prefix |
scopes |
repo:read, repo:write, repo:admin, org:read, usage:read |
At least one required |
repository_id |
UUID | Required for REPO tokens |
expires_in_days |
int | Omit for a token that never expires |
{ "token": { "id": "6f1a…", "name": "github-actions/vision-build", "kind": "CI", "prefix": "cavs_ci", "scopes": ["repo:write"], "expires_at": "2026-10-26T12:00:00Z" }, "secret": "cavs_ci_9dK2…"}Only the SHA-256 hash is stored. Counts against the plan’s token limit (402 when
exceeded). Both actions are audited. Full guidance:
API tokens.
Webhooks
Section titled “Webhooks”| Endpoint | Permission | |
|---|---|---|
| GET | /organizations/{orgID}/webhooks |
organization.update |
| POST | /organizations/{orgID}/webhooks |
organization.update |
| PATCH | /organizations/{orgID}/webhooks/{webhookID} |
organization.update |
| DELETE | /organizations/{orgID}/webhooks/{webhookID} |
organization.update |
| GET | /organizations/{orgID}/webhooks/{webhookID}/deliveries |
organization.update |
curl -sS -X POST "$API/organizations/$ORG/webhooks" -H "$H" -H "$J" \ -d '{"url": "https://hooks.example.com/cavs", "events": ["repository.push", "release.published"]}'| Field | Notes |
|---|---|
url |
Must be a valid http/https URL with a host |
events |
At least one. "*" subscribes to everything and collapses the list. |
The signing secret is generated by CAVS (whsec_…) and returned once in the
create response.
PATCH accepts url, events and active. Setting active: true also clears the
circuit breaker. A webhook is auto-disabled after 10 consecutive failures.
Full detail — payloads, signature verification, retries: Webhooks.
Storage connections (BYOS)
Section titled “Storage connections (BYOS)”| Endpoint | Permission | |
|---|---|---|
| GET | /organizations/{orgID}/storage/connections |
storage.read |
| POST | /organizations/{orgID}/storage/connections |
storage.manage |
| GET | /organizations/{orgID}/storage/connections/{connID} |
storage.read |
| PATCH | /organizations/{orgID}/storage/connections/{connID} |
storage.manage |
| POST | /organizations/{orgID}/storage/connections/{connID}/test |
storage.manage |
| DELETE | /organizations/{orgID}/storage/connections/{connID} |
storage.manage |
curl -sS -X POST "$API/organizations/$ORG/storage/connections" -H "$H" -H "$J" \ -d '{ "name": "acme-prod-eu", "provider": "aws_s3", "region": "eu-central-1", "bucket": "acme-cavs-prod", "prefix": "cavs/", "auth_method": "access_keys", "access_key_id": "AKIA…", "secret_access_key": "…" }'| Field | Notes |
|---|---|
name |
Display name |
provider |
aws_s3, r2, wasabi, b2, minio, generic |
scope |
Connection scope |
endpoint, region, bucket, prefix |
Target. A prefix is strongly recommended. |
path_style, tls_verify |
Booleans, provider-dependent |
kms_key_id, storage_class |
Optional |
auth_method |
access_keys or assume_role |
access_key_id, secret_access_key |
For access_keys |
role_arn, external_id |
For assume_role |
The secret is encrypted with AES-256-GCM before it touches the database and is never returned by any response. Creating or testing runs the seven-check connectivity suite and records the result as the connection’s health.
402 quota_exceeded if your plan doesn’t allow BYOS (or the add-on isn’t active), or
at the connection limit.
Full guide: Bring Your Own S3.
Billing
Section titled “Billing”| Endpoint | Permission | |
|---|---|---|
| GET | /organizations/{orgID}/billing |
billing.read |
| POST | /organizations/{orgID}/billing/checkout |
billing.update |
| POST | /organizations/{orgID}/billing/portal |
billing.update |
| POST | /organizations/{orgID}/billing/confirm |
billing.update |
| POST | /organizations/{orgID}/billing/byos-addon |
billing.update |
billing.read / billing.update belong to OWNER and BILLING — not ADMIN.
# Current plan, subscription state, usage against limits, invoice previewcurl -sS "$API/organizations/$ORG/billing" -H "$H"
# Start a checkout for a paid plan → { "url": "…" }curl -sS -X POST "$API/organizations/$ORG/billing/checkout" -H "$H" -H "$J" \ -d '{"plan_id": "team"}'
# Open the provider's billing portal → { "url": "…" }curl -sS -X POST "$API/organizations/$ORG/billing/portal" -H "$H"
# Confirm a checkout that the webhook hasn't landed yetcurl -sS -X POST "$API/organizations/$ORG/billing/confirm" -H "$H" -H "$J" \ -d '{"plan_id": "team"}'
# Toggle the Developer BYOS add-oncurl -sS -X POST "$API/organizations/$ORG/billing/byos-addon" -H "$H" -H "$J" \ -d '{"enabled": true}'checkout and portal return a url to redirect the user to. confirm may return
202 Accepted with {"status": "pending_webhook"} when the provider hasn’t confirmed
yet — poll GET …/billing.
A plan without a configured provider price fails checkout. free never checks out and
business is contact-sales, so neither has one.
See Managing your subscription.
POST /api/v1/billing/webhook
Section titled “POST /api/v1/billing/webhook”The billing provider’s callback. Public — verified by provider signature rather than a bearer token, and not something you call.
Audit log
Section titled “Audit log”GET /organizations/{orgID}/audit
Section titled “GET /organizations/{orgID}/audit”Permission: audit.read — ADMIN or OWNER. Team and Business plans.
curl -sS "$API/organizations/$ORG/audit" -H "$H"- Endpoint index — every route in one table.
- Roles & permissions — who can call what.

