---
title: Organizations
description: Read the active organization, manage members, and send / revoke invites. Admin or owner role required for mutations.
section: API Reference
order: 14
---
The Developer API key carries an organization scope. Every endpoint
operates on that org — there is no cross-org access from a single key.
Use these endpoints to read org metadata, manage members, and handle
invites.

```python
from pictograph import Client
client = Client()
```

## me

Fetch the active organization (the one the API key belongs to).

```python
org = client.organizations.me()
print(org.id, org.name, org.subscription_tier, org.member_count)
```

Returns `Organization` with tier (`free` / `core` / `pro` / `enterprise`),
billing email, monthly credit allowance, etc.

## list_members

```python
for m in client.organizations.list_members():
    print(m.email, m.role, m.joined_at)
```

Returns `list[OrganizationMember]`.

## update_member_role

Promote / demote a member. `member_id` is the row's UUID, **not** the
underlying user UUID.

```python
client.organizations.update_member_role(
    member_id="member-uuid",
    role="admin",     # viewer / member / admin / owner
)
```

Role hierarchy: callers may set roles ≤ their own. An `admin` cannot
promote anyone to `owner`.

## remove_member

```python
client.organizations.remove_member(member_id="member-uuid")
```

The user's account is preserved — only the org membership is revoked.
They can be re-invited.

## list_invites

```python
invites = client.organizations.list_invites(status="pending")
for inv in invites:
    print(inv.email, inv.role, inv.expires_at, inv.invite_url)
```

Filter by `status` ∈ `{"pending", "accepted", "revoked", "expired"}`
or `None` for all.

## invite

```python
invite = client.organizations.invite(
    email="new@example.com",
    role="member",
    expires_in_days=14,        # optional; defaults to 7
)
print("Send this link:", invite.invite_url)
```

Returns `OrganizationInvite` with a one-time `invite_url`. Email
delivery is automatic when SMTP is configured server-side; if you
disabled email, share the URL manually.

## revoke_invite

```python
client.organizations.revoke_invite(invite_id="invite-uuid")
```

Sets the invite's `status` to `"revoked"` immediately. The URL stops
working.

## Permission matrix

| Op | Min role |
|---|---|
| `me`, `list_members`, `list_invites` | `viewer` |
| `update_member_role`, `invite`, `revoke_invite` | `admin` |
| `remove_member` | `admin` (can't remove `owner` unless caller is `owner`) |

## Common errors

| Status | Exception | Cause |
|---|---|---|
| 403 | `ForbiddenError` | Caller's role too low for the action |
| 404 | `NotFoundError` | `member_id` / `invite_id` doesn't exist (or belongs to another org) |
| 409 | `ConflictError` | `invite` to an email that's already a member |
| 422 | `ValidationError` | Invalid role, malformed email |