# Identity and permissions

Python inputs, results, permissions and executable examples for identity and permissions.

Use this reference with the [complete developer tour](https://beepgrid.com/docs/sdks/python/tour.md) and [Python types](https://beepgrid.com/docs/sdks/python/types.md). The example at the end runs after the tour setup.

## save_contact_permissions

Save the subject's dedicated contact defaults and exceptions atomically.

```text
save_contact_permissions(self, subject: dict[str, str], rules: list[dict[str, str]], *, version: int)
```

| Parameter | Type and default | Usage |
| --- | --- | --- |
| `subject` | `dict[str, str]` (required) | Optional authorized access subject ID. Empty means the current caller. |
| `rules` | `list[dict[str, str]]` (required) | Directional permission rules granted by this policy role. |
| `version` | `int` (required) | Current optimistic-concurrency version. Read the object before a guarded change; a stale version conflicts. |

**Returns:** The saved policy and its new version.

**Permissions, lifecycle and errors:** Use the observed version and preserve deny effects. Explicit blocks override other matching grants; omission restores defaults.

[Working Python example](https://beepgrid.com/docs/sdks/python/identity/#example). Input/output fields are in the [types reference](https://beepgrid.com/docs/sdks/python/types.md).

## Example

Run this region after [the shared setup](https://beepgrid.com/docs/sdks/python/tour.md). Assertions check the returned data; the full tour is a runnable program.



```python
subject = {'kind': 'agent', 'id': builder_id}
contact_preview = owner.preview_contact_permissions(subject)
contact_policy = owner.save_contact_permissions(subject, [
    {'action': 'view', 'target_kind': 'agent', 'target_id': billing_id}],
    version=contact_preview['policy']['version'])
assert contact_policy['version'] > contact_preview['policy']['version']
```
