---
title: Sharing
path: api-guides/sharing
status: published
---

Internal sharing: shares, members, and invitations. Everything that happens inside your tenant with people who have (or will have) accounts.

For sharing content with anonymous users via public URLs, see [External Links](/docs/scaidrive/api-guides/external-links).

**Base path:** `/api/v1/shares/`

## Creating a share

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/shares \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 Planning",
    "share_type": "project",
    "owner_id": "grp_01J3L"
  }'
```

```python
resp = httpx.post(
    f"{url}/api/v1/shares",
    headers={"Authorization": f"Bearer {token}"},
    json={"name": "Q2 Planning", "share_type": "project", "owner_id": "grp_01J3L"},
)
share = resp.json()
```

```typescript
const resp = await fetch(`${url}/api/v1/shares`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Q2 Planning",
    share_type: "project",
    owner_id: "grp_01J3L",
  }),
});
const share = await resp.json();
```

Fields:

| Field | Notes |
|-------|-------|
| `name` (required) | Display name |
| `share_type` (required) | `central`, `personal`, or `project` |
| `owner_id` (required) | `usr_...` or `grp_...` — who owns the share |
| `description` | Optional |
| `quota_bytes` | Optional; omit to inherit tenant quota |

See [Shares and Ownership](/docs/scaidrive/core-concepts/shares-and-ownership) for the types.

## Listing your shares

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/users/me/shares
```

Returns shares you're a member of (directly or via a group), with your role in each.

To list all shares in the tenant (admin view):

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/shares
```

Query parameters `limit`, `offset`, and `include_trashed` apply.

## Searching for principals

Before adding a member, look up the user or group:

```bash
curl -G $SCAIDRIVE_URL/api/v1/shares/search/principals \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  --data-urlencode "q=alice" \
  --data-urlencode "principal_type=user"
```

```json
{
  "users": [
    {"id": "usr_01J4M", "email": "alice@example.com", "name": "Alice Cooper"}
  ],
  "groups": []
}
```

Search hits `email`, `name`, and `display_name`. Omit `principal_type` to search both users and groups.

## Adding a member

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/members \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "principal_type": "user",
    "principal_id": "usr_01J4M",
    "role": "contributor"
  }'
```

With time-bounded access:

```json
{
  "principal_type": "user",
  "principal_id": "usr_01J4M",
  "role": "reader",
  "expires_at": "2026-07-01T00:00:00Z"
}
```

Requires `MANAGE_PERMISSIONS` on the share — effectively `owner` or `admin` role.

Role options: `owner`, `admin`, `contributor`, `reader`. See [Shares and Ownership](/docs/scaidrive/core-concepts/shares-and-ownership).

## Listing members

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/members
```

```json
{
  "members": [
    {
      "principal_type": "group",
      "principal_id": "grp_01J3L",
      "principal_name": "Engineering",
      "role": "admin",
      "granted_by": "usr_01J3N",
      "expires_at": null
    },
    {
      "principal_type": "user",
      "principal_id": "usr_01J4M",
      "principal_name": "Alice Cooper",
      "role": "contributor",
      "granted_by": "usr_01J3N",
      "expires_at": "2026-07-01T00:00:00Z"
    }
  ],
  "total": 2
}
```

## Changing a member's role

```bash
curl -X PATCH $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/members/usr_01J4M \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "admin"}'
```

You can also change `expires_at`.

## Removing a member

```bash
curl -X DELETE $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/members/usr_01J4M \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Revoking group membership removes access for every user in that group (unless they have direct membership in addition).

## Inviting someone who doesn't have an account

For users not yet provisioned in ScaiKey, send an invitation:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/invite \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "partner@external.com",
    "role": "reader",
    "message": "Here are the specs we discussed.",
    "expires_in_days": 14
  }'
```

Response:

```json
{
  "id": "inv_01J5N",
  "email": "partner@external.com",
  "role": "reader",
  "status": "pending",
  "token": "opaque-invitation-token",
  "expires_at": "2026-05-07T10:15:00Z"
}
```

An email is sent via ScaiSend with a link containing the token. When the recipient clicks:

1. They authenticate via ScaiKey (creating an account if new).
2. ScaiDrive provisions the user JIT.
3. They call `POST /api/v1/users/me/invitations/{invitation_id}/accept`.
4. A `ShareMember` record is created with the invitation's role.

Pending invitations for the calling user:

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/users/me/invitations
```

Accept or decline:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/users/me/invitations/inv_01J5N/accept \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"

curl -X POST $SCAIDRIVE_URL/api/v1/users/me/invitations/inv_01J5N/decline \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Revoke a pending invitation:

```bash
curl -X DELETE $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/invitations/inv_01J5N \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

## Listing pending invitations on a share

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/shares/shr_01J3K/invitations
```

Returns invitations with status `pending`. Filter by status if you want the history — `?status=all`.

## Per-file and per-folder access

Sometimes you want to grant one person access to one file within a share they're not a member of. For that, use the ACL API directly:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/permissions/acl/file/fil_01J3M \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "principal_type": "user",
    "principal_id": "usr_01J4M",
    "permissions": ["READ"],
    "ace_type": "allow",
    "inherit_to_children": false
  }'
```

This doesn't make them a share member — they can access the file, but not see or list the share. See [Permissions and ACLs](/docs/scaidrive/core-concepts/permissions-and-acls).

For external parties without any ScaiDrive account, use [External Links](/docs/scaidrive/api-guides/external-links).

## Updating the share itself

```bash
curl -X PATCH $SCAIDRIVE_URL/api/v1/shares/shr_01J3K \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Q2 Planning (archived)"}'
```

Requires `MANAGE_PERMISSIONS`. You can change `name` and `description`.

## Deleting a share

```bash
curl -X DELETE $SCAIDRIVE_URL/api/v1/shares/shr_01J3K \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"
```

Soft-deletes the share. Content is preserved for the tenant's trash-retention window. Permanent deletion requires tenant admin.

## Common recipes

### Give a group read-only access

```python
httpx.post(
    f"{url}/api/v1/shares/{share_id}/members",
    headers={"Authorization": f"Bearer {token}"},
    json={"principal_type": "group", "principal_id": group_id, "role": "reader"},
)
```

### Time-bounded contractor access

```python
import datetime as dt

expires = (dt.datetime.now(dt.UTC) + dt.timedelta(days=90)).isoformat()
httpx.post(
    f"{url}/api/v1/shares/{share_id}/members",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "principal_type": "user",
        "principal_id": contractor_id,
        "role": "contributor",
        "expires_at": expires,
    },
)
```

### Invite several external users at once

```python
for email in ["a@ext.com", "b@ext.com", "c@ext.com"]:
    httpx.post(
        f"{url}/api/v1/shares/{share_id}/invite",
        headers={"Authorization": f"Bearer {token}"},
        json={"email": email, "role": "reader", "expires_in_days": 30},
    )
```

## What's next

- [External Links](/docs/scaidrive/api-guides/external-links) — sharing with people who don't have accounts.
- [Shares Reference](/docs/scaidrive/reference/shares) — all share endpoints.
- [Permissions and ACLs](/docs/scaidrive/core-concepts/permissions-and-acls) — resource-level permissions.