> ## Documentation Index
> Fetch the complete documentation index at: https://docs.outerlayer.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Organization API

> Manage members, roles, the audit log and context sources from a script, with a management API key.

The organization API is the set of endpoints under `/v1/orgs/{orgName}/`. They do what the organization's **Settings** pages do: invite and remove members, change roles, read the audit log, and choose where a factory's context comes from.

`{orgName}` is the organization's name as it appears in the dashboard URL, `/orgs/<orgName>/`. Case does not matter.

## Choose a credential

| Credential | Used by | Plan |
| - | - | - |
| Management API key (`olk_...`) | Scripts and automation | Enterprise |
| A signed-in member's session | The dashboard's **Settings** pages | Every plan |

The dashboard calls these endpoints with your session, so it works on every plan. Scripts need a management API key, which needs Enterprise.

A factory's API key (`sk_outerlayer_...`) never works here. It belongs to one factory, and these endpoints act on the whole organization. See [API keys](/api-keys) for factory keys.

## Create a management API key

Open the organization's **Settings → Management API keys** and choose **Create key**. The tab shows on an Enterprise plan, to members who can view org API keys.

Name the key after what will use it, and tick the permissions it needs. You can grant only permissions you hold yourself. The key is shown once, and it is not shown again.

A key never does more than the member who created it can do now. Every call checks the key's permissions against its creator's current role. If the creator moves to a lower role, the key loses the permissions that role lacks. A key is refused with `403` when its creator has left the organization, or holds a custom role. Create keys from a member with a built-in role who will stay.

Send it as a bearer token:

```bash theme={"system"}
curl https://api.outerlayer.ai/v1/orgs/acme/members \
  -H "Authorization: Bearer <management key>"
```

To rotate a key, create a new one, move your script to it, then revoke the old one from the same tab.

After an organization leaves Enterprise, its keys are refused with `402`. The tab no longer shows in the menu, but revoking still works. Open `/orgs/<orgName>/settings/management-api-keys` directly to revoke them.

## Permissions

A management key carries organization permissions only. Each endpoint needs one:

| Permission | Allows |
| - | - |
| `org.read` | List members and pending invites. |
| `members.insert` | Invite a member, and resend a pending invite. |
| `members.update` | Change a member's role. |
| `members.delete` | Remove a member. |
| `roles.read` | List the built-in roles. The key dialog labels it **View custom roles**. |
| `audit.read` | Read and export the audit log. |
| `governance.read` | Read a factory's context source. |
| `governance.insert` | Designate a factory's context source, or change whether saves to it need a pull request. |
| `governance.delete` | Revoke a factory's context source. |

The key dialog also offers `roles.insert`, `roles.update` and `roles.delete`. No endpoint in this API uses them.

A signed-in member needs the same permission, from their role in the organization.

## Members and roles

| Method | Path | Does |
| - | - | - |
| `GET` | `/v1/orgs/{orgName}/members` | Lists active members and pending invites. |
| `POST` | `/v1/orgs/{orgName}/members/invites` | Invites someone by `name`, `email` and `role`. |
| `POST` | `/v1/orgs/{orgName}/members/invites/{inviteId}/resend` | Sends a pending invite's email again. |
| `PATCH` | `/v1/orgs/{orgName}/members/{userId}` | Changes a member's `role`. |
| `DELETE` | `/v1/orgs/{orgName}/members/{userId}` | Removes a member. |
| `GET` | `/v1/orgs/{orgName}/roles` | Lists the built-in roles. |

The built-in roles are `owner`, `admin`, `write`, `read` and `disabled`.

To invite someone, send their name, email and role:

```bash theme={"system"}
curl -X POST https://api.outerlayer.ai/v1/orgs/acme/members/invites \
  -H "Authorization: Bearer <management key>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "<full name>", "email": "<email>", "role": "write" }'
```

The key needs `members.insert`. A sent invite answers `200` with the new membership's id:

```json theme={"system"}
{ "data": { "membershipId": "<membership-id>" } }
```

The invite email goes out at once. Resend it with `POST /v1/orgs/{orgName}/members/invites/{inviteId}/resend`.

To give someone a custom role, send its id as `custom_role_id` beside `role`, on an invite or a role change. Custom roles need a Team or Enterprise plan. A role that belongs to another organization is refused with `400 custom_role_not_found`.

An invite cannot give access to individual factories. A non-empty `appRoles` is refused with `400 app_roles_not_supported`. Set factory access from **Settings → Members** once the invite is sent.

Changes made through the API are recorded in the audit log. A change made with a key names the key, and a change made with a session names the person.

## Audit log

The audit log needs an Enterprise plan, whichever credential calls it.

| Method | Path | Does |
| - | - | - |
| `GET` | `/v1/orgs/{orgName}/audit-log` | Lists entries, newest first, one page at a time. |
| `GET` | `/v1/orgs/{orgName}/audit-log/{logId}` | Returns one entry in full. |
| `GET` | `/v1/orgs/{orgName}/audit-log/export` | Returns the whole log as CSV, oldest first. |

The list takes these query parameters, all optional:

| Parameter | Filters by |
| - | - |
| `actionType` | The action, such as `permission_vocabulary_retired`. |
| `targetType` | What the action changed. |
| `startDate`, `endDate` | A date (`2026-09-01`) or a UTC timestamp (`2026-09-01T12:00:00Z`). |
| `page`, `pageSize` | Which page, and how many entries per page: 25 by default, at most 100. |

The response carries `data` and `pagination`, where `pagination.totalPages` tells you when to stop.

The export takes no filters. It holds at most 50,000 rows.

```bash theme={"system"}
curl https://api.outerlayer.ai/v1/orgs/acme/audit-log/export \
  -H "Authorization: Bearer <management key>" \
  -o audit-log.csv
```

## Context sources

A factory's context source can be read, designated, changed and revoked at `/v1/orgs/{orgName}/apps/{appId}/context-source`. See [Manage it through the API](/share-instructions-across-repositories#manage-it-through-the-api).

## Errors

An error response carries `error.code` and `error.message`.

| Status | Means |
| - | - |
| `400` | The body is invalid (`invalid_request_body`), or the change breaks a rule, such as a non-owner inviting an owner. `error.message` says which rule. A custom role from another organization is `custom_role_not_found`. |
| `401` | The key is unknown, or the signed-in caller is not a member of this organization. An organization that does not exist answers the same way. |
| `402` | The plan does not include what the call needs. `error.code` is `entitlement_required`, and `error.entitlement` names it: `management_api`, `audit_log` or `custom_roles`. |
| `403` | The credential lacks the endpoint's permission, or the key belongs to another organization. A key whose creator has left or holds a custom role gets `403` too. |
| `404` | The member, pending invite, audit log entry or factory is not in this organization. Check the id. |
| `409` | A context source conflicts: the factory already has one (`context_source_exists`), or the repository is another factory's (`context_source_repository_in_use`). Revoke the existing one first. |

Every endpoint's full request and response schema is in the API reference, under [Org Management](/api-reference/org-management/list-an-orgs-audit-log) and **Context**.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.