Code Examples
C.O.S. API v1
Full curl and Python examples for every endpoint. For the interactive API browser, see API Reference.
Setup
export COS_API_KEY="cos_live_your_key_here"
export ORG_ID="your-organisation-uuid"
export BASE="https://cosprotocol.io/v1"
import requests
API_KEY = "cos_live_your_key_here"
ORG_ID = "your-organisation-uuid"
BASE = "https://cosprotocol.io/v1"
AUTH = {"Authorization": f"Bearer {API_KEY}"}
Unauthenticated endpoints
GET /health
GET /version
Organisations
GET /organisations — list all (platform key required)
resp = requests.get(f"{BASE}/organisations", headers=AUTH, params={"limit": 20})
data = resp.json()
for org in data["data"]:
print(org["id"], org["name"])
next_cursor = data["meta"]["next_cursor"] # None if last page
POST /organisations — create org (platform key required)
curl -s -X POST \
-H "Authorization: Bearer $COS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "slug": "acme-corp"}' \
$BASE/organisations
resp = requests.post(
f"{BASE}/organisations",
headers={**AUTH, "Content-Type": "application/json"},
json={"name": "Acme Corp", "slug": "acme-corp"},
)
org = resp.json()
print(org["id"]) # new UUID
Note:
industry_sectionis read-only — do not include it in the request body.slugis set once and cannot be changed later.
GET /organisations/{id}
PUT /organisations/{id} — full update
curl -s -X PUT \
-H "Authorization: Bearer $COS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corporation"}' \
$BASE/organisations/$ORG_ID
resp = requests.put(
f"{BASE}/organisations/{ORG_ID}",
headers={**AUTH, "Content-Type": "application/json"},
json={"name": "Acme Corporation"},
)
PATCH /organisations/{id} — partial update
curl -s -X PATCH \
-H "Authorization: Bearer $COS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp Ltd"}' \
$BASE/organisations/$ORG_ID
resp = requests.patch(
f"{BASE}/organisations/{ORG_ID}",
headers={**AUTH, "Content-Type": "application/json"},
json={"name": "Acme Corp Ltd"},
)
Members
GET /organisations/{id}/members
cursor = None
while True:
params = {"limit": 50}
if cursor:
params["cursor"] = cursor
resp = requests.get(
f"{BASE}/organisations/{ORG_ID}/members",
headers=AUTH, params=params,
)
data = resp.json()
for member in data["data"]:
print(member["id"], member["email"])
cursor = data["meta"]["next_cursor"]
if not cursor:
break
API Keys
GET /organisations/{id}/api-keys — list keys
resp = requests.get(f"{BASE}/organisations/{ORG_ID}/api-keys", headers=AUTH)
for key in resp.json()["data"]:
print(key["id"], key["key_prefix"], "active:", key["is_active"])
POST /organisations/{id}/api-keys — issue a key
curl -s -X POST \
-H "Authorization: Bearer $COS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"label": "CI pipeline"}' \
$BASE/organisations/$ORG_ID/api-keys
resp = requests.post(
f"{BASE}/organisations/{ORG_ID}/api-keys",
headers={**AUTH, "Content-Type": "application/json"},
json={"label": "CI pipeline"},
)
new_key = resp.json()
# IMPORTANT: save new_key["key"] now — it is returned only once
print("Raw key (store this now):", new_key["key"])
print("Key ID for revocation:", new_key["id"])
DELETE /organisations/{id}/api-keys/{key_id} — revoke
curl -s -X DELETE \
-H "Authorization: Bearer $COS_API_KEY" \
$BASE/organisations/$ORG_ID/api-keys/$KEY_ID
# Returns 204 No Content
resp = requests.delete(
f"{BASE}/organisations/{ORG_ID}/api-keys/{KEY_ID}",
headers=AUTH,
)
assert resp.status_code == 204, f"Revocation failed: {resp.status_code}"
print("Key revoked.")
Revocation is permanent. The key is immediately rejected at authentication. A governance event (
api_key_revoked) is written to the C.O.S. audit log. There is no undo.