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

# Organization API

> Manage members, roles, the audit log and control planes 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. They 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

Scripts send a management API key (`olk_...`), which needs an Enterprise plan. The dashboard's **Settings** pages call the same endpoints with a member's session, so they work on every plan. A factory API key (`sk_outerlayer_...`) never works here, because it belongs to one factory. See [Authenticate](/api-reference/introduction#authenticate) for every credential, and [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 organization 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 control plane. |
| `governance.insert` | Set a factory's control plane, or change whether edits to it need a pull request. |
| `governance.delete` | Remove a factory's control plane. |

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
```

## Control planes

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

## Errors

[Errors](/api-reference/introduction#errors) gives the error body and what each status means. These are particular to the organization endpoints:

| Status | Means |
| - | - |
| `400` | 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 signed-in caller is not a member of this organization. An organization that does not exist answers the same way. |
| `402` | `error.entitlement` is `management_api`, `audit_log` or `custom_roles`. |
| `403` | The key belongs to another organization, or its creator has left or holds a custom role. |
| `409` | The repository is already another factory's control plane (`context_source_repository_in_use`). Remove it from that factory first. |
| `422` | The repository is not one the factory links (`repository_not_linked`), or its branch or `.outerlayer/config.json` could not be read (`context_source_unreadable`). Link it 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.