> ## Documentation Index
> Fetch the complete documentation index at: https://turnkey-0e7c1f5b-omkar-time-based-policies.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Access control

> This page provides examples of policies governing access generally.

#### Allow a specific user to create wallets

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to create wallets",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.resource == 'WALLET' && activity.action == 'CREATE'"
}
```

#### Allow users with a specific tag to create users

```json theme={"system"}
{
  "policyName": "Allow user_tag <USER_TAG_ID> to create users",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.tags.contains('<USER_TAG_ID>'))",
  "condition": "activity.resource == 'USER' && activity.action == 'CREATE'"
}
```

#### Require two users with a specific tag to add policies

```json theme={"system"}
{
  "policyName": "Require two users with user_tag <USER_TAG_ID> to create policies",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.filter(user, user.tags.contains('<USER_TAG_ID>')).count() >= 2",
  "condition": "activity.resource == 'POLICY' && activity.action == 'CREATE'"
}
```

#### Deny all delete actions for users with a specific tag

```json theme={"system"}
{
  "policyName": "Only user_tag <USER_TAG_ID> can take actions",
  "effect": "EFFECT_DENY",
  "consensus": "approvers.any(user, user.tags.contains('<USER_TAG_ID>'))",
  "condition": "activity.action == 'DELETE'"
}
```

#### Allow a specific user (e.g. API-only user) to create a sub-org

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to create a sub-org",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.resource == 'ORGANIZATION' && activity.action == 'CREATE'"
}
```

#### Allow a specific user to perform auth type activities (full list [here](/features/policies/language#activity-breakdown))

Note: The `activity.resource` portion determines which activities can be performed. The `activity.action` determines what types of actions can be taken upon those resources.

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to initiate auth type activities",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.resource == 'AUTH' && activity.action == 'CREATE'"
}
```

#### Allow a specific user to perform [generic OTP](/api-reference/activities/init-generic-otp) activities

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to initiate and verify generic OTP activities",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.resource in ['AUTH', 'OTP'] && activity.action in ['CREATE','VERIFY']"
}
```

#### Allow a specific user to perform a specific activity type (full list [here](/features/policies/language#activity-breakdown))

Note: Activities may be upgraded over time, and thus new versions may be introduced.
These policies will NOT be valid if an activity type is upgraded and requests are made on the new activity type.
For example, if Turnkey introduces `ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V3` (upgraded from `ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2`)
and a request is made with the newer `V3` version, this policy with not allow that user to perform `ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V3` activities.

```json JSON theme={"system"}
{
  "policyName": "Allow user <USER_ID> to perform create read write session v2",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.type == 'ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2'"
}
```

#### Allow a specific user to perform a specific activity kind (full list [here](/features/policies/language#activity-kinds))

Unlike `activity.type`, which targets one exact version, `activity.kind` is version-agnostic: a
single `kind` matches every version of an activity. Prefer `activity.kind` when you want a policy to
keep working as activities are upgraded. For example, the policy below continues to allow the user to
create read write sessions even if Turnkey introduces a newer version such as
`ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V3`, because `CREATE_READ_WRITE_SESSION` matches all
versions.

Not sure whether to use `type`, `kind`, or `resource` + `action`? See [Choosing between `type`, `kind`, and `resource` + `action`](/features/policies/language#choosing-between-type-kind-and-resource--action) for guidance.

```json JSON theme={"system"}
{
  "policyName": "Allow user <USER_ID> to create read write sessions (any version)",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.kind == 'CREATE_READ_WRITE_SESSION'"
}
```

#### Allow a specific user to sign transactions across all versions

```json JSON theme={"system"}
{
  "policyName": "Allow user <USER_ID> to sign transactions (any version)",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<YOUR_API_USER_ID>')",
  "condition": "activity.kind == 'SIGN_TRANSACTION'"
}
```

#### Allow a specific credential type to perform a specific action (full list of credential types [here](/features/users/credentials#credential-types))

This policy can be used to say, only passkeys are allowed to sign transactions and not authentication through SMS (or any other authentication method).

```json JSON theme={"system"}
{
  "policyName": "Allow signing with only passkeys",
  "effect": "EFFECT_ALLOW",
  "consensus": "credentials.any(credential, credential.type == 'CREDENTIAL_TYPE_WEBAUTHN_AUTHENTICATOR')",
  "condition": "activity.type == 'ACTIVITY_TYPE_SIGN_TRANSACTION_V2'"
}
```

#### Allow a specific credential with a specific public key type to perform a specific action

```json JSON theme={"system"}
{
  "policyName": "Allow signing with only passkeys",
  "effect": "EFFECT_ALLOW",
  "consensus": "credentials.any(credential, credential.public_key == '<YOUR_CREDENTIAL_PUBLIC_KEY>')",
  "condition": "activity.type == 'ACTIVITY_TYPE_SIGN_TRANSACTION_V2'"
}
```

#### Allow exporting only a specific wallet account address

```json JSON theme={"system"}
{
  "policyName": "Allow exporting only wallet account <WALLET_ACCOUNT_ADDRESS>",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.action == 'EXPORT' && wallet_account.address == '<WALLET_ACCOUNT_ADDRESS>'"
}
```

#### Time-based policies

The optional top-level `time` field gates **when** a policy is active. It is authored in the policy
language, must evaluate to a `bool`, and is evaluated against trusted server time. When `time` is
absent or empty the policy is always active; when it evaluates to `false` the policy is skipped for
that request. See [Time](/features/policies/language#time) in the language reference for full
details on `time.now`, `Timestamp(...)`, and `CronSpan(...)`.

#### Grant a user temporary access for a fixed window (one-shot)

This policy allows the user to sign transactions only during January 2025 (UTC). The window is
start-inclusive and end-exclusive, so it becomes active at `2025-01-01T00:00:00Z` and inactive at
`2025-02-01T00:00:00Z`. Outside the window the `time` field evaluates to `false` and the policy is
skipped.

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to sign transactions during January 2025",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.kind == 'SIGN_TRANSACTION'",
  "time": "time.now >= Timestamp('2025-01-01T00:00:00Z') && time.now < Timestamp('2025-02-01T00:00:00Z')"
}
```

#### Allow signing only during business hours

`CronSpan` fires once at 9:00 AM Eastern on weekdays and holds each window open for 8 hours, covering
9:00 AM–5:00 PM Monday through Friday. Because the time zone is IANA-based, the window follows
daylight saving automatically.

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to sign during business hours",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.kind == 'SIGN_TRANSACTION'",
  "time": "CronSpan('0 9 * * 1-5', '8h', 'America/New_York')"
}
```

<Note>
  Model business hours as one fire plus an 8-hour duration. Do not use an hour-range cron like
  `0 9-17 * * 1-5` to mean "9 to 5": under the fire-plus-duration model that opens a separate window
  at every hour and will not produce a single continuous span.
</Note>

#### Allow signing during an overnight window (crossing midnight)

A window that crosses midnight needs no special handling: fire in the evening and give it a duration
that runs into the next morning. This opens a window every night at 10:00 PM Eastern that stays
active until 6:00 AM.

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to sign overnight",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.kind == 'SIGN_TRANSACTION'",
  "time": "CronSpan('0 22 * * *', '8h', 'America/New_York')"
}
```

#### Bound a recurring window to a fixed date range (composed)

Because `time` is a boolean expression, you can intersect a recurring span with a one-shot bound.
This grants business-hours signing, but only through the end of 2025; afterward the `&&` makes the
whole expression `false`.

```json theme={"system"}
{
  "policyName": "Allow user <USER_ID> to sign during business hours through 2025",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.id == '<USER_ID>')",
  "condition": "activity.kind == 'SIGN_TRANSACTION'",
  "time": "CronSpan('0 9 * * 1-5', '8h', 'America/New_York') && time.now < Timestamp('2026-01-01T00:00:00Z')"
}
```

#### Full policy combining consensus, condition, and time

The `time` field composes with the other policy fields: this policy applies only when the approver,
the request, and the current time all match. Here, members of the ops team may sign transactions to
the treasury address, but only during business hours.

```json theme={"system"}
{
  "policyName": "Ops may sign to treasury during business hours",
  "effect": "EFFECT_ALLOW",
  "consensus": "approvers.any(user, user.tags.contains('<OPS_TAG_ID>'))",
  "condition": "activity.kind == 'SIGN_TRANSACTION' && eth.tx.to == '<TREASURY_ADDRESS>'",
  "time": "CronSpan('0 9 * * 1-5', '8h', 'America/New_York')"
}
```
