---
title: Access control in CloudBehaviours
product: Cloud Code
version: 3.0.0
latest_version: 3.0.0
status: This page documents version 3.0.0. The latest version is 3.0.0.
canonical: https://docs.unity.com/en-us/cloud-code/3.0.0/cloudbehaviours/access-control
latest_url: https://docs.unity.com/en-us/cloud-code/3.0.0/cloudbehaviours/access-control.md
last_updated: 2026-10-23
generated_at: 2026-11-04T14:20:30.793Z
locale: en-us
---

# Access control in CloudBehaviours

> Understand the access levels that control which callers can call a CloudBehaviour endpoint, and when to use each one.

> **Important:**
>
> This page describes an experimental feature that might change significantly before release. It's not recommended to use or rely on experimental features in production environments due to potential instability.

Every CloudBehaviour endpoint has an access level. By default, Cloud Code resolves the access level from the class's `[StateScope]`. A `Scope.Player` class defaults to `Access.Player`, and a `Scope.MultiplayerSession` class defaults to `Access.SessionMember`.

## Override the default access level

Add `[CloudCodeAccess]` only where a specific endpoint needs to differ from the scope's default. The following example keeps the default on one endpoint and overrides it on two others:

```csharp title="Overriding the default access level"
[StateScope(Scope.MultiplayerSession)]
public class MatchState : CloudBehaviour
{
    // This endpoint uses the default access level, Access.SessionMember.
    public void SubmitMove(string move) { }

    // Only the session host can call this endpoint.
    [CloudCodeAccess(Access.SessionHost)]
    public void StartMatch() { }

    // Only non-player callers, such as a timer, can call this endpoint.
    [CloudCodeAccess(Access.Service)]
    public void EndTurn(int turnNumber) { }
}
```

## Access levels

The following table lists each `Access` value, the scopes it's valid on, and who can call an endpoint that uses it:

| Value           | Valid on                        | Who can call                                                                                                                                        |
| :-------------- | :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Unspecified`   | Any scope                       | Resolves from the class scope at load time (the default): `Access.Player` for `Scope.Player`, `Access.SessionMember` for `Scope.MultiplayerSession` |
| `Global`        | Any scope                       | Any authenticated caller                                                                                                                            |
| `Service`       | Any scope                       | Non-player callers only, such as other CloudBehaviours, service accounts, or trusted backends, never a player                                       |
| `Player`        | `Scope.Player` only             | The player who owns the scope, and any non-player caller                                                                                            |
| `SessionMember` | `Scope.MultiplayerSession` only | Any member of the session, and any non-player caller                                                                                                |
| `SessionHost`   | `Scope.MultiplayerSession` only | The host of the session, and any non-player caller                                                                                                  |

If you set an `Access` value that the class's scope doesn't support, the module throws an exception when it loads.

## Choose an access level

Use `Access.Service` on an endpoint that only a non-player caller has a reason to call, such as a timer callback, or an endpoint that another CloudBehaviour calls to update a player's record. If logic only runs as part of another endpoint, such as granting gold when a player makes a move, make it a private method instead. A private method isn't an endpoint, so no client can call it. Use `Access.SessionHost` for match flow control, such as starting or force-advancing a match, where one client is authoritative. In other cases, the scope's default access level is usually correct.

> **Important:**
>
> Access control restricts who can call an endpoint, but not who receives the changes the endpoint makes. When any endpoint changes synchronized state, the new state reaches every client in the scope. To keep data private, use a private field, or refer to [Per-player state views in CloudBehaviours](./per-player-state-views.md).

For example, clients can't call an `Access.Service` endpoint, but they still receive the synchronized state that the endpoint changes.

## Additional resources

* [Multiplayer game security in CloudBehaviours](./secure-multiplayer-game-logic.md)
* [Timers in CloudBehaviours](./timers.md)
* [Cross-behaviour calls in CloudBehaviours](./calling-another-behaviour.md)
