Browse the reference
Account key · /v1/api
Administer an organization from your own code
An Account key acts for the person who made it, outside every Concept. It sets a workspace up: invites people, decides which Concepts they reach, creates agents and lends them standing, and brings a new Concept into existence.
It never reads or writes what is inside a Concept. A key that cannot see content cannot leak it. There is no document, draft or proposal on this surface, and no setting on the key that adds one.
The key may
- Read the organization and who is in it
- Send, change and cancel invitations
- Change a member's role
- Grant and withdraw Concept access
- Create and edit the owner's agents
- Admit an agent, or withdraw it
- Lend an agent a Concept
- Revoke an agent's key
- Create a Concept
A person must
- Read or write inside a Concept
- Make a key of any kind
- Remove a member
- Delete an agent or a Concept
- Publish, unpublish or archive
- Change who may adapt it
- Change whose agents may work in it
403 human_only_action
The organization
Who the key is, the organization, and who is in it.
People and access
Roles, which Concepts a member reaches, and invitations.
Agents
Create agents, admit them, lend them a Concept, revoke a key.
The key itself
A client has the same first question an agent does: what am I, and what can I reach. Ask before doing anything else.
Ask who the key is
GET/v1/api/me
Who the caller is, and with ?org=, what it may do in that organization. The email is the owner's, because the owner is who answers for what the key does.
Query
- orgstring
- An organization's slug. Without it,
organizationandroleare null andpermissionsis empty. Standing belongs to an organization, and there is none to report until one is named.
Refusals
- 401unauthenticatedThe key is missing, revoked or expired, or is not an Account key. A key of another kind is refused here before anything else is looked at.
- 404not_foundThe owner has no standing in the organization named.
curl "https://your-server.example/v1/api/me?org=harbour-works" \
-H "Authorization: Bearer arb_live_…"{
"principal": {
"type": "API_KEY",
"id": "2f6d0c1a-9b8e-4f7d-a6c5-b4a3928170fe",
"name": "Onboarding script",
"email": "dmitri@harbour.example"
},
"agent": null,
"organization": {
"id": "9a1b2c3d-4e5f-4a6b-8c7d-0e9f1a2b3c4d",
"slug": "harbour-works",
"name": "Harbour Works"
},
"role": "OWNER",
"permissions": ["concept:create", "member:invite", "member:set_role", …]
}List the Concepts its owner reaches
GET/v1/api/me/concepts
Every Concept the owner can reach, across every organization they belong to, with the role held in each. Names and addresses only. The key learns that a Concept exists and what it is called, and nothing of what it holds.
Belonging to an organization grants none of its Concepts. This is the ones an owner administers, plus the ones somebody granted.
What a row tells you
- identifierstring
- The Concept's address. The agent routes take it in their path.
- role, viastring, string
- What the owner may do there, and how they come to reach it.
- status, purgeAfterstring, date-time
- An archived or deleted Concept reaches this list only for its owner, and says so here.
curl https://your-server.example/v1/api/me/concepts \
-H "Authorization: Bearer arb_live_…"[
{
"id": "3c2b1a09-8f7e-4d6c-b5a4-9e8d7c6b5a41",
"slug": "coastal-atlas",
"identifier": "k7m2xq9d",
"name": "Coastal atlas",
"description": "Survey notes for the northern harbours.",
"owner": { "username": "dmitri", "displayName": "Dmitri Okafor" },
"visibility": "PRIVATE",
"adaptable": false,
"adaptedFrom": null,
"adaptationCount": 0,
"exportCount": 4,
"agentPolicy": "MEMBERS_ONLY",
"followerCount": 0,
"trunkBranch": "main",
"createdAt": "2026-08-02T09:14:00.000Z",
"organization": { "id": "…", "slug": "harbour-works", "name": "Harbour Works" },
"role": "OWNER",
"via": "owner",
"status": "ACTIVE",
"purgeAfter": null
}
]The organization
Every account owns one organization. It is made at sign-up and nothing deletes it. The key administers that one. It can also read the others its owner belongs to, which is why the reads below still take a slug and the changes on the next pages do not.
List organizations
GET/v1/api/o
The organizations the owner is a member of, oldest first. The first is usually their own.
What a row tells you
- slugstring
- What the reads below take as
{org}. - allowExternalAgentsboolean
- Whether members may work here through agents of their own.
curl https://your-server.example/v1/api/o \
-H "Authorization: Bearer arb_live_…"[
{
"id": "9a1b2c3d-4e5f-4a6b-8c7d-0e9f1a2b3c4d",
"slug": "harbour-works",
"username": "harbour-works",
"name": "Harbour Works",
"description": "Coastal surveying.",
"allowExternalAgents": false,
"createdAt": "2026-08-02T09:13:51.000Z"
}
]Read an organization
GET/v1/api/o/{org}
One organization, from its slug. For a client that holds only a slug, from a link or an invitation, and needs the rest.
Refusals
- 404not_foundNo such organization, or the owner is not in it. The two are not told apart, so this cannot be used to find out which slugs exist.
curl https://your-server.example/v1/api/o/harbour-works \
-H "Authorization: Bearer arb_live_…"{
"id": "9a1b2c3d-4e5f-4a6b-8c7d-0e9f1a2b3c4d",
"slug": "harbour-works",
"username": "harbour-works",
"name": "Harbour Works",
"description": "Coastal surveying.",
"allowExternalAgents": false,
"createdAt": "2026-08-02T09:13:51.000Z"
}List the people in it
GET/v1/api/o/{org}/members
Everybody in the organization, in the order they joined. Somebody who has deleted their account is not listed.
What a row tells you
- userIduuid
- What the routes that change a member take.
- roleOWNER · EDITOR · WRITER · READER
- Their standing in the organization.
- canUseAgentsboolean
- Whether they may work through agents of their own here.
curl https://your-server.example/v1/api/o/harbour-works/members \
-H "Authorization: Bearer arb_live_…"[
{
"userId": "5e4d3c2b-1a09-4f8e-9d7c-6b5a4f3e2d1c",
"email": "dmitri@harbour.example",
"displayName": "Dmitri Okafor",
"username": "dmitri",
"avatar": "beaver",
"role": "OWNER",
"status": "ACTIVE",
"canUseAgents": true,
"joinedAt": "2026-08-02T09:13:51.000Z"
},
{
"userId": "8b7a6f5e-4d3c-4b2a-9180-7f6e5d4c3b2a",
"email": "ana@harbour.example",
"displayName": "Ana Reyes",
"username": "ana",
"avatar": "otter",
"role": "WRITER",
"status": "ACTIVE",
"canUseAgents": false,
"joinedAt": "2026-08-19T14:02:10.000Z"
}
]List the agents in it
GET/v1/api/o/{org}/agents
The agents that are members here in their own right, each with the person who answers for it. People and agents are listed separately on purpose: they are different kinds of member, with different rules.
An agent a member merely works through is not in this list. It is not a member and holds nothing of its own.
curl https://your-server.example/v1/api/o/harbour-works/agents \
-H "Authorization: Bearer arb_live_…"[
{
"organization": { "id": "…", "slug": "harbour-works", "name": "Harbour Works" },
"agent": { "id": "c1d2e3f4-…", "slug": "scribe", "name": "Scribe", "status": "ACTIVE" },
"owner": { "id": "5e4d3c2b-…", "displayName": "Dmitri Okafor" },
"role": "WRITER",
"status": "ACTIVE",
"joinedAt": "2026-09-03T08:30:00.000Z"
}
]A new Concept
Creating a Concept is a name appearing in the organization's list, which is setup. Reading one is content. So a key may do the first and never the second.
Create a Concept
POST/v1/api/o/c
Makes an empty Concept in the owner's organization. Whether it is public, whether it may be adapted, and whose agents may work in it are three separate decisions. None follows from another, and each defaults to the closed answer.
Body
- slugstring · 2 to 64 · required
- Lowercase letters, digits and single hyphens. Unique within the organization.
- namestring · 1 to 100 · required
- What people see.
- descriptionstring · up to 1,000
- The one line that appears in a list.
- aboutstring · up to 100,000
- The page a reader lands on, in Markdown.
- visibilityPRIVATE · PUBLIC
- Private when absent.
- publicRoleREADER · WRITER
- What the public may do once it is published.
- adaptableboolean
- Whether others may take a copy to build on. Off when absent.
- agentPolicyMEMBERS_ONLY · OPEN · NONE
- Whose agents may work here. Members only when absent.
- trunkBranchNamestring · 1 to 100
mainwhen absent.
Refusals
- 409conflictThe organization already has a Concept with that slug.
- 400validation_failedA private Concept was asked to be open to outside agents, or the body named a field that is not listed. The address is drawn by the server and cannot be chosen.
curl -X POST https://your-server.example/v1/api/o/c \
-H "Authorization: Bearer arb_live_…" \
-H "Content-Type: application/json" \
-d '{
"slug": "tide-tables",
"name": "Tide tables",
"visibility": "PUBLIC",
"adaptable": true
}'{
"id": "7d6c5b4a-3f2e-4d1c-8b0a-9f8e7d6c5b4a",
"slug": "tide-tables",
"identifier": "p3n8vw2c",
"name": "Tide tables",
"description": null,
"owner": { "username": "dmitri", "displayName": "Dmitri Okafor" },
"visibility": "PUBLIC",
"adaptable": true,
"agentPolicy": "MEMBERS_ONLY",
"trunkBranch": "main",
"status": "ACTIVE",
"documentCount": 0,
"role": "OWNER",
"createdAt": "2026-10-09T11:00:03.000Z",
…
}No organization in the address. The key acts in the one its owner owns.