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

# Project Membership Events

> Audit log events for project access management and role changes

<Info>
  Project membership events track when users are added to, removed from, or have their roles changed within projects.
</Info>

## project\_membership.create

Triggered when a user is added to a project with a specific role. Only project owners can add members.

### Event Schema

<ResponseField name="action" type="string" required>
  Always set to `"project_membership.create"`
</ResponseField>

<ResponseField name="actor" type="object" required>
  The user who added the new member

  <Expandable title="properties">
    <ResponseField name="type" type="string" required>
      Always set to `"user"`
    </ResponseField>

    <ResponseField name="id" type="string" required>
      User's unique identifier
    </ResponseField>

    <ResponseField name="name" type="string" required>
      User's full name
    </ResponseField>

    <ResponseField name="metadata" type="object" required>
      <Expandable title="properties">
        <ResponseField name="first_name" type="string" required>
          User's first name
        </ResponseField>

        <ResponseField name="last_name" type="string" required>
          User's last name
        </ResponseField>

        <ResponseField name="email" type="string" required>
          User's email address
        </ResponseField>

        <ResponseField name="impersonator_email" type="string">
          Email of admin impersonating the user
        </ResponseField>

        <ResponseField name="impersonator_reason" type="string">
          Reason for impersonation
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="targets" type="array" required>
  Three targets: the project, organization membership, and the user being added

  <Expandable title="target objects">
    <ResponseField name="project" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"project"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Project's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Project's name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="name" type="string" required>
              Project's name
            </ResponseField>

            <ResponseField name="organization_id" type="string" required>
              Organization containing the project
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="organization_membership" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"organization_membership"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Organization membership identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Member's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="organization_id" type="string" required>
              Organization identifier
            </ResponseField>

            <ResponseField name="role_slug" type="string" required>
              Member's organization role (e.g., `"member"`, `"admin"`)
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="user" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"user"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          User's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          User's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="first_name" type="string" required>
              User's first name
            </ResponseField>

            <ResponseField name="last_name" type="string" required>
              User's last name
            </ResponseField>

            <ResponseField name="email" type="string" required>
              User's email address
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="context" type="object" required>
  <Expandable title="properties">
    <ResponseField name="location" type="string" required>
      IP address or `"unknown"`
    </ResponseField>

    <ResponseField name="userAgent" type="string" required>
      User agent string or `"unknown"`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object" required>
  <Expandable title="properties">
    <ResponseField name="source" type="string" required>
      Page route where member was added (e.g., `"/projects/{id}/members"`)
    </ResponseField>

    <ResponseField name="role" type="string" required>
      Project role assigned: `"owner"`, `"editor"`, or `"viewer"`
    </ResponseField>
  </Expandable>
</ResponseField>

### Example

```json theme={null}
{
  "action": "project_membership.create",
  "occurredAt": "2024-11-02T18:30:00.000Z",
  "version": 1,
  "actor": {
    "type": "user",
    "id": "user_01JBKQ8Z...",
    "name": "Alice Johnson",
    "metadata": {
      "first_name": "Alice",
      "last_name": "Johnson",
      "email": "alice@company.com",
      "impersonator_email": "",
      "impersonator_reason": ""
    }
  },
  "targets": [
    {
      "type": "project",
      "id": "proj_abc123",
      "name": "Production API",
      "metadata": {
        "name": "Production API",
        "organization_id": "org_xyz789"
      }
    },
    {
      "type": "organization_membership",
      "id": "om_def456",
      "name": "Bob Smith",
      "metadata": {
        "organization_id": "org_xyz789",
        "role_slug": "member"
      }
    },
    {
      "type": "user",
      "id": "user_02JBKQ9A...",
      "name": "Bob Smith",
      "metadata": {
        "first_name": "Bob",
        "last_name": "Smith",
        "email": "bob@company.com"
      }
    }
  ],
  "context": {
    "location": "203.0.113.1",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
  },
  "metadata": {
    "source": "/projects/proj_abc123/members",
    "role": "editor"
  }
}
```

***

## project\_membership.update

Triggered when a project member's role is changed. Only project owners can update member roles. Users cannot modify their own membership.

### Event Schema

<ResponseField name="action" type="string" required>
  Always set to `"project_membership.update"`
</ResponseField>

<ResponseField name="actor" type="object" required>
  The user who changed the member's role

  <Expandable title="properties">
    <ResponseField name="type" type="string" required>
      Always set to `"user"`
    </ResponseField>

    <ResponseField name="id" type="string" required>
      User's unique identifier
    </ResponseField>

    <ResponseField name="name" type="string" required>
      User's full name
    </ResponseField>

    <ResponseField name="metadata" type="object" required>
      <Expandable title="properties">
        <ResponseField name="first_name" type="string" required>
          User's first name
        </ResponseField>

        <ResponseField name="last_name" type="string" required>
          User's last name
        </ResponseField>

        <ResponseField name="email" type="string" required>
          User's email address
        </ResponseField>

        <ResponseField name="impersonator_email" type="string">
          Email of admin impersonating the user
        </ResponseField>

        <ResponseField name="impersonator_reason" type="string">
          Reason for impersonation
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="targets" type="array" required>
  Three targets: the project, organization membership, and the user whose role changed

  <Expandable title="target objects">
    <ResponseField name="project" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"project"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Project's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Project's name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="name" type="string" required>
              Project's name
            </ResponseField>

            <ResponseField name="organization_id" type="string" required>
              Organization containing the project
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="organization_membership" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"organization_membership"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Organization membership identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Member's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="organization_id" type="string" required>
              Organization identifier
            </ResponseField>

            <ResponseField name="role_slug" type="string" required>
              Member's organization role
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="user" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"user"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          User's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          User's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="first_name" type="string" required>
              User's first name
            </ResponseField>

            <ResponseField name="last_name" type="string" required>
              User's last name
            </ResponseField>

            <ResponseField name="email" type="string" required>
              User's email address
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="context" type="object" required>
  <Expandable title="properties">
    <ResponseField name="location" type="string" required>
      IP address or `"unknown"`
    </ResponseField>

    <ResponseField name="userAgent" type="string" required>
      User agent string or `"unknown"`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object" required>
  <Expandable title="properties">
    <ResponseField name="source" type="string" required>
      Page route where role was updated (e.g., `"/projects/{id}/members"`)
    </ResponseField>

    <ResponseField name="old_role" type="string" required>
      Previous project role: `"owner"`, `"editor"`, or `"viewer"`
    </ResponseField>

    <ResponseField name="new_role" type="string" required>
      New project role: `"owner"`, `"editor"`, or `"viewer"`
    </ResponseField>
  </Expandable>
</ResponseField>

### Example

```json theme={null}
{
  "action": "project_membership.update",
  "occurredAt": "2024-11-02T18:35:00.000Z",
  "version": 1,
  "actor": {
    "type": "user",
    "id": "user_01JBKQ8Z...",
    "name": "Alice Johnson",
    "metadata": {
      "first_name": "Alice",
      "last_name": "Johnson",
      "email": "alice@company.com",
      "impersonator_email": "",
      "impersonator_reason": ""
    }
  },
  "targets": [
    {
      "type": "project",
      "id": "proj_abc123",
      "name": "Production API",
      "metadata": {
        "name": "Production API",
        "organization_id": "org_xyz789"
      }
    },
    {
      "type": "organization_membership",
      "id": "om_def456",
      "name": "Bob Smith",
      "metadata": {
        "organization_id": "org_xyz789",
        "role_slug": "member"
      }
    },
    {
      "type": "user",
      "id": "user_02JBKQ9A...",
      "name": "Bob Smith",
      "metadata": {
        "first_name": "Bob",
        "last_name": "Smith",
        "email": "bob@company.com"
      }
    }
  ],
  "context": {
    "location": "203.0.113.1",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
  },
  "metadata": {
    "source": "/projects/proj_abc123/members",
    "old_role": "viewer",
    "new_role": "editor"
  }
}
```

***

## project\_membership.delete

Triggered when a user is removed from a project. Only project owners can remove members. Users cannot remove themselves.

### Event Schema

<ResponseField name="action" type="string" required>
  Always set to `"project_membership.delete"`
</ResponseField>

<ResponseField name="actor" type="object" required>
  The user who removed the member

  <Expandable title="properties">
    <ResponseField name="type" type="string" required>
      Always set to `"user"`
    </ResponseField>

    <ResponseField name="id" type="string" required>
      User's unique identifier
    </ResponseField>

    <ResponseField name="name" type="string" required>
      User's full name
    </ResponseField>

    <ResponseField name="metadata" type="object" required>
      <Expandable title="properties">
        <ResponseField name="first_name" type="string" required>
          User's first name
        </ResponseField>

        <ResponseField name="last_name" type="string" required>
          User's last name
        </ResponseField>

        <ResponseField name="email" type="string" required>
          User's email address
        </ResponseField>

        <ResponseField name="impersonator_email" type="string">
          Email of admin impersonating the user
        </ResponseField>

        <ResponseField name="impersonator_reason" type="string">
          Reason for impersonation
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="targets" type="array" required>
  Three targets: the project, organization membership, and the user being removed

  <Expandable title="target objects">
    <ResponseField name="project" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"project"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Project's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Project's name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="name" type="string" required>
              Project's name
            </ResponseField>

            <ResponseField name="organization_id" type="string" required>
              Organization containing the project
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="organization_membership" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"organization_membership"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          Organization membership identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Member's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="organization_id" type="string" required>
              Organization identifier
            </ResponseField>

            <ResponseField name="role_slug" type="string" required>
              Member's organization role
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="user" type="object" required>
      <Expandable title="properties">
        <ResponseField name="type" type="string" required>
          Set to `"user"`
        </ResponseField>

        <ResponseField name="id" type="string" required>
          User's unique identifier
        </ResponseField>

        <ResponseField name="name" type="string" required>
          User's full name
        </ResponseField>

        <ResponseField name="metadata" type="object" required>
          <Expandable title="properties">
            <ResponseField name="first_name" type="string" required>
              User's first name
            </ResponseField>

            <ResponseField name="last_name" type="string" required>
              User's last name
            </ResponseField>

            <ResponseField name="email" type="string" required>
              User's email address
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="context" type="object" required>
  <Expandable title="properties">
    <ResponseField name="location" type="string" required>
      IP address or `"unknown"`
    </ResponseField>

    <ResponseField name="userAgent" type="string" required>
      User agent string or `"unknown"`
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object" required>
  <Expandable title="properties">
    <ResponseField name="source" type="string" required>
      Page route where member was removed (e.g., `"/projects/{id}/members"`)
    </ResponseField>

    <ResponseField name="role" type="string" required>
      Project role before removal: `"owner"`, `"editor"`, or `"viewer"`
    </ResponseField>
  </Expandable>
</ResponseField>

### Example

```json theme={null}
{
  "action": "project_membership.delete",
  "occurredAt": "2024-11-02T18:40:00.000Z",
  "version": 1,
  "actor": {
    "type": "user",
    "id": "user_01JBKQ8Z...",
    "name": "Alice Johnson",
    "metadata": {
      "first_name": "Alice",
      "last_name": "Johnson",
      "email": "alice@company.com",
      "impersonator_email": "",
      "impersonator_reason": ""
    }
  },
  "targets": [
    {
      "type": "project",
      "id": "proj_abc123",
      "name": "Production API",
      "metadata": {
        "name": "Production API",
        "organization_id": "org_xyz789"
      }
    },
    {
      "type": "organization_membership",
      "id": "om_def456",
      "name": "Bob Smith",
      "metadata": {
        "organization_id": "org_xyz789",
        "role_slug": "member"
      }
    },
    {
      "type": "user",
      "id": "user_02JBKQ9A...",
      "name": "Bob Smith",
      "metadata": {
        "first_name": "Bob",
        "last_name": "Smith",
        "email": "bob@company.com"
      }
    }
  ],
  "context": {
    "location": "203.0.113.1",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
  },
  "metadata": {
    "source": "/projects/proj_abc123/members",
    "role": "editor"
  }
}
```

***

## Project Roles

Project memberships use three role levels:

<ResponseField name="owner" type="string">
  Full project access including member management, settings changes, and resource deletion
</ResponseField>

<ResponseField name="editor" type="string">
  Create and manage API keys and MCP proxies. Cannot manage members or project settings
</ResponseField>

<ResponseField name="viewer" type="string">
  Read-only access to project resources and analytics
</ResponseField>

<Tip>
  Only users who are already members of the organization can be added to projects. Project membership requires existing organization membership.
</Tip>

## Common Patterns

### Member Addition Flow

1. Organization owner invites user to organization
2. Project owner adds organization member to project with specific role
3. `project_membership.create` event logs the addition

### Permission Changes

Role updates from the project members page create `project_membership.update` events with before and after roles in metadata. This tracks all permission changes for compliance and security auditing.

### Access Removal

When a project owner removes a member, the `project_membership.delete` event records the user's role at time of removal. The member retains organization membership but loses project access.
