Projects
Create projects, add repositories and members, and share them with invitations.
| Operation | Request |
|---|---|
| List projects | GET /v1/projects |
| Create project | POST /v1/projects |
| Accept project invitation | POST /v1/projects/invitations/accept |
| Preview project invitation | POST /v1/projects/invitations/preview |
| Get project | GET /v1/projects/{id} |
| Update project | PATCH /v1/projects/{id} |
| Delete project | DELETE /v1/projects/{id} |
| Get project repository access | GET /v1/projects/{id}/access |
| Create project invitation | POST /v1/projects/{id}/invitations |
| Leave project | POST /v1/projects/{id}/leave |
| List project members | GET /v1/projects/{id}/members |
| Set project member role | PATCH /v1/projects/{id}/members/{member} |
| Remove project member | DELETE /v1/projects/{id}/members/{member} |
| Add project repository | POST /v1/projects/{id}/repositories |
| Remove project repository | DELETE /v1/projects/{id}/repositories/{owner}/{name} |
List projects
GET /v1/projects · listProjects
List owned and currently shared projects, oldest first. This is not a snapshot. Limit defaults to 100 and clamps to 1–200. The after value must name an entry still present in this account's list; after a 400 invalid_cursor response, restart the list.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | No | Clamped to 1–200. |
after | query | string | No | Last project ID from this same list. Empty means the first page. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectList
| Field | Type | Required | Description |
|---|---|---|---|
data | array of AppProjectObject | Yes | |
data[].id | string | Yes | |
data[].object | always "project" | Yes | |
data[].name | string | Yes | |
data[].instructions | string or null | Yes | |
data[].repositories | array of AppProjectRepository | Yes | |
data[].repositories[].repository | string | Yes | |
data[].repositories[].primary | boolean | Yes | |
data[].repositories[].default_branch | string | Yes | |
data[].repositories[].private | boolean | Yes | |
data[].repository | string or null | Yes | |
data[].default_branch | string or null | Yes | |
data[].private | boolean | Yes | |
data[].created_at | string (date-time) | Yes | |
data[].updated_at | string (date-time) | Yes | |
data[].protection | one of "standard", "only_me" | Yes | |
data[].counts | object | Yes | |
data[].counts.threads | integer | Yes | |
data[].counts.files | integer | Yes | |
data[].counts.documents | integer | Yes | |
data[].counts.sources | integer | Yes | |
data[].role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
data[].members | integer | Yes | |
data[].shared | boolean | Yes | |
next | string or null | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl 'https://api.openagents.com/v1/projects' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Create project
POST /v1/projects · createProject
Create a new project each time; no idempotency deduplication. Maximum 200 owned and shared projects per account. GitHub repositories require the caller's connected GitHub access. Project creation precedes applying protection and reading file metadata: a later error can leave the project created. Inspect the list before retrying an uncertain result.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Request body
Content type: application/json
Type: AppProjectCreate
| Field | Type | Required | Description |
|---|---|---|---|
name | string or null | No | Trimmed, nonempty, at most 100 characters. Omit to use the first repository's name. |
instructions | string or null | No | At most 8,000 characters after cleaning; blank instructions become null. |
repository | string or null | No | Older single-repository input; combined with repositories. |
repositories | array of string | No | Connected GitHub owner/name values; at most 20 distinct repositories. |
protection | one of "standard", "only_me", null | No |
Response
201 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Example project"
}'
Accept project invitation
POST /v1/projects/invitations/accept · acceptProjectInvitation
Join with a valid single-use invitation. Existing members keep their current role without consuming the invitation. Maximum 100 members per project and 200 projects per account. Membership is committed before shared-chat bookkeeping; inspect membership after an uncertain response instead of assuming failure means nothing changed.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Request body
Content type: application/json
Type: AppProjectInvitationCode
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The invitation code or its full link. Query and fragment suffixes are ignored. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects/invitations/accept' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"code": "string"
}'
Preview project invitation
POST /v1/projects/invitations/preview · previewProjectInvitation
Authenticated preview of a working invitation without consuming it. The code grants this preview; normal project reads still need membership. Expired, invalid or consumed codes return 404 invitation_not_found.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Request body
Content type: application/json
Type: AppProjectInvitationCode
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The invitation code or its full link. Query and fragment suffixes are ignored. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectInvitationPreview
| Field | Type | Required | Description |
|---|---|---|---|
object | always "project.invitation" | Yes | |
project | object | Yes | |
project.id | string | Yes | |
project.name | string | Yes | |
role | one of "editor", "viewer" | Yes | |
invited_by | string | Yes | |
expires_at | string (date-time) | Yes | |
member | one of "owner", "editor", "viewer", null | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects/invitations/preview' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"code": "string"
}'
Get project
GET /v1/projects/{id} · getProject
Read a currently accessible project. IDs and name:NAME are accepted; duplicate exact names return 409 ambiguous_name. A foreign project or removed membership returns 404 not_found.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl 'https://api.openagents.com/v1/projects/{id}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Update project
PATCH /v1/projects/{id} · updateProject
Owners rename or change protection; editors can change instructions and repository selection. Viewers cannot edit. Protection is applied before other edits, so a later error can leave an earlier change saved. No transaction or idempotency deduplication is promised.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Request body
Content type: application/json
Type: AppProjectEdit (object or any or object)
| Field | Type | Required | Description |
|---|---|---|---|
repository | null | No | Only null is ignored; any other repository field is refused. |
name | string or null | No | An owner can rename the project. Trimmed and limited to 100 characters. |
instructions | string or null | No | Omission leaves instructions unchanged; null clears them. Limited to 8,000 characters after cleaning. |
primary_repository | string or null | No | Choose a repository already attached to this project. Null leaves the primary unchanged. |
protection | one of "standard", "only_me", null | No | Owner only; a shared project cannot become only_me. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X PATCH 'https://api.openagents.com/v1/projects/{id}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"instructions": null
}'
Delete project
DELETE /v1/projects/{id} · deleteProject
Owner only. Returns 409 project_has_threads unless detach_threads=true when this caller has attached chats. Deletion removes project files/documents and keeps detached chats. Cleanup follows account-service deletion; a failure can leave partial cleanup. Inspect state after uncertain results. A repeated deletion returns 404.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
detach_threads | query | boolean | No |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectDeleted
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project.deleted" | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X DELETE 'https://api.openagents.com/v1/projects/{id}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Get project repository access
GET /v1/projects/{id}/access · getProjectRepositoryAccess
Check this caller's own GitHub access to each project repository. Project membership does not grant repository credentials. A false access result is not permission to run code or read a repository through another member's token.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectRepositoryAccess
| Field | Type | Required | Description |
|---|---|---|---|
data | array of object | Yes | |
data[].repository | string | Yes | |
data[].access | boolean | Yes | |
data[].message | string or null | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl 'https://api.openagents.com/v1/projects/{id}/access' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Create project invitation
POST /v1/projects/{id}/invitations · createProjectInvitation
Owner only; only_me projects cannot be shared. Each request makes a new invitation code, returned here only. At most 50 open invitations are kept; a new one replaces the oldest beyond that limit. No idempotency deduplication. A GitHub-targeted notification is best effort; the invitation can exist even if recording that notice fails.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Request body
Content type: application/json
Type: AppProjectInvite
| Field | Type | Required | Description |
|---|---|---|---|
role | one of "editor", "viewer", null | No | Default: |
expires_in | integer or null | No | Seconds. Missing, null or zero uses seven days; other values clamp to 600–2,592,000 seconds. Default: |
github | string or null | No | Optional GitHub login to receive an invitation on their Projects page. This lookup needs the configured GitHub service. |
Response
201 — The result, with Cache-Control: no-store, private.
Type: AppProjectInvitation
| Field | Type | Required | Description |
|---|---|---|---|
object | always "project.invitation" | Yes | |
invitee | object or null | Yes | |
invitee.github | string | No | |
id | string | Yes | |
project | string | Yes | |
role | one of "editor", "viewer" | Yes | |
code | string | Yes | |
url | string (uri) | Yes | |
expires_at | string (date-time) | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects/{id}/invitations' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"role": "editor",
"expires_in": 604800,
"github": "string"
}'
Leave project
POST /v1/projects/{id}/leave · leaveProject
Leave a shared project. Its owner must transfer ownership first (409 owner_stays). No chat execution or repository deletion occurs. After leaving, another request for this project returns 404.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectLeft
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project.left" | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects/{id}/leave' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
List project members
GET /v1/projects/{id}/members · listProjectMembers
Any current member can list members and their own role. This list is not paginated (next is null); only the owner sees open invitation metadata. Invitation codes are never listed.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectMembers
| Field | Type | Required | Description |
|---|---|---|---|
data | array of AppProjectMember | Yes | |
data[].account | string | Yes | |
data[].object | always "project.member" | Yes | |
data[].name | string or null | Yes | |
data[].login | string or null | Yes | |
data[].role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
data[].joined_at | string (date-time) | Yes | |
data[].you | boolean | Yes | |
next | null | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
invitations | array of object | No | Present only for the owner; does not expose invitation codes. |
invitations[].id | string | Yes | |
invitations[].role | one of "editor", "viewer" | Yes | |
invitations[].expires_at | string (date-time) | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl 'https://api.openagents.com/v1/projects/{id}/members' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Set project member role
PATCH /v1/projects/{id}/members/{member} · setProjectMemberRole
Owner only. Set an existing member's editor/viewer role or transfer ownership with owner. Exactly one owner remains. Recheck roles after an uncertain transfer; do not assume the caller still owns the project.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
member | path | string | Yes | An account ID of a current member. |
Request body
Content type: application/json
Type: AppProjectSetRole
| Field | Type | Required | Description |
|---|---|---|---|
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X PATCH 'https://api.openagents.com/v1/projects/{id}/members/{member}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"role": "owner"
}'
Remove project member
DELETE /v1/projects/{id}/members/{member} · removeProjectMember
Owner can remove another member. Removing yourself uses leave semantics and returns project.left; an owner must transfer ownership before leaving. Removed members lose access on the next request.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
member | path | string | Yes | An account ID of a current member. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectMemberRemoved (AppProjectLeft or object)
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X DELETE 'https://api.openagents.com/v1/projects/{id}/members/{member}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"
Add project repository
POST /v1/projects/{id}/repositories · addProjectRepository
Owner or editor, with their own connected GitHub access. At most 20 repositories. The first is primary; primary=true selects the added repository. Adding an already attached repository does not add a duplicate.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
Request body
Content type: application/json
Type: AppProjectAddRepository
| Field | Type | Required | Description |
|---|---|---|---|
repository | string | Yes | |
primary | boolean | No | Default: |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X POST 'https://api.openagents.com/v1/projects/{id}/repositories' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"repository": "string"
}'
Remove project repository
DELETE /v1/projects/{id}/repositories/{owner}/{name} · removeProjectRepository
Owner or editor. Remove the named repository; removing the primary selects the first remaining repository. This does not delete a GitHub repository or its files.
Sign-in: a bearer credential in the Authorization header.
projectManagementBearer: A live account-service app session (sess_) or sign-in key (oa_sk_). These web handlers reject cookies alone and oak_ API keys. Every request resolves the account and current project role; knowing an ID does not grant access.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID or name:NAME; exact duplicate names are ambiguous. |
owner | path | string | Yes | A GitHub repository path segment. |
name | path | string | Yes | A GitHub repository path segment. |
Response
200 — The result, with Cache-Control: no-store, private.
Type: AppProjectObject
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | |
object | always "project" | Yes | |
name | string | Yes | |
instructions | string or null | Yes | |
repositories | array of AppProjectRepository | Yes | |
repositories[].repository | string | Yes | |
repositories[].primary | boolean | Yes | |
repositories[].default_branch | string | Yes | |
repositories[].private | boolean | Yes | |
repository | string or null | Yes | |
default_branch | string or null | Yes | |
private | boolean | Yes | |
created_at | string (date-time) | Yes | |
updated_at | string (date-time) | Yes | |
protection | one of "standard", "only_me" | Yes | |
counts | object | Yes | |
counts.threads | integer | Yes | |
counts.files | integer | Yes | |
counts.documents | integer | Yes | |
counts.sources | integer | Yes | |
role | AppProjectRole (one of "owner", "editor", "viewer") | Yes | |
members | integer | Yes | |
shared | boolean | Yes |
Errors
| Status | Meaning | Body |
|---|---|---|
| 400 | invalid_request, invalid_cursor or not_available (sealed protection). Invalid typed query parameters can instead return framework text/plain errors. | AppAccountError |
| 401 | signed_out: missing, unsupported, expired or revoked credential. | AppAccountError |
| 403 | project_role or github_refused: the current role or GitHub grant does not allow the action. | AppAccountError |
| 404 | not_found or invitation_not_found: unavailable to this account, removed membership, or an unusable invitation. | AppAccountError |
| 409 | ambiguous_name, project_has_threads, full, github_not_connected, github_reconnect, owner_stays, project_full, shared_project or only_me_project. | AppAccountError |
| 429 | rate_limited: GitHub throttled the request. No Retry-After or automatic mutation retry guarantee. | AppAccountError |
| 502 |
| AppAccountError |
| 503 | unavailable: account or chat/file storage could not be reached. | AppAccountError |
Example
curl -X DELETE 'https://api.openagents.com/v1/projects/{id}/repositories/{owner}/{name}' \
-H "Authorization: Bearer $OPENAGENTS_TOKEN"