> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# OpalScript Reference

> Learn language basics and quickly reference OpalScript functions.

## Language Basics

OpalScript uses [Starlark syntax](https://bazel.build/rules/language), which is similar to Python. This section gives you a quick overview of Starlark syntax and its key differences from Python.

### Syntax Overview

```python theme={null}
# Variables
count = 10
name = "alice"
is_active = True

# Conditionals
if count > 5:
    print("high")
elif count > 0:
    print("low")
else:
    print("zero")

# Loops
for item in [1, 2, 3]:
    print(item)

for i in range(10):
    print(i)

# Functions
def calculate_score(base, multiplier):
    return base * multiplier

# String operations
text = "Hello World"
lower_text = text.lower()          # "hello world"
contains_hello = "hello" in lower_text  # True

# Lists
items = ["a", "b", "c"]
items.append("d")
first = items[0]

# Dictionaries
config = {"key": "value", "count": 42}
value = config["key"]
config["new_key"] = "new_value"
```

### Key Differences from Python

OpalScript (Starlark) has some intentional limitations compared to Python:

| Feature           | OpalScript                               | Python       |
| ----------------- | ---------------------------------------- | ------------ |
| Import statements | Not supported (modules pre-loaded)       | Supported    |
| Classes           | Not supported                            | Supported    |
| Exceptions        | Not supported (`try`/`except`)           | Supported    |
| While loops       | Not supported (use `for` with `range()`) | Supported    |
| Global variables  | Limited mutation                         | Full support |
| Standard library  | Minimal                                  | Extensive    |

These limitations ensure scripts are predictable, terminate reliably, and execute safely.

## Quick Reference

### Utility Functions (All Script Types)

| Module           | Function                                                                            | Description                                                            |
| ---------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| accesslib        | `check_access(principal, entity, [level])`                                          | Check whether a principal has access to an entity                      |
| notificationslib | `notify_user(user_id, title, body)`                                                 | Notify a specific user via email and Slack (if configured)             |
| notificationslib | `notify_admins(title, body)`                                                        | Notify all Opal admins                                                 |
| notificationslib | `notify_owner(owner_id, title, body)`                                               | Notify an owner via Slack channel (if configured) or all owner members |
| assetlib         | `get_resource_risk_sensitivity(resource_id)`                                        | Get the risk sensitivity level of a resource                           |
| assetlib         | `get_group_risk_sensitivity(group_id)`                                              | Get the risk sensitivity level of a group                              |
| assetlib         | `get_requests_for_resource(resource_id, [user_id], [status], [cursor], [per_page])` | Get historical requests for a resource (paginated)                     |
| assetlib         | `get_requests_for_group(group_id, [user_id], [status], [cursor], [per_page])`       | Get historical requests for a group (paginated)                        |
| userlib          | `get_requests(user_id, [status], [cursor], [per_page])`                             | Get requests a user submitted or was the target of (paginated)         |
| timelib          | `now()`                                                                             | Get the current Unix timestamp                                         |
| timelib          | `from_unix(timestamp)`                                                              | Convert a Unix timestamp to an RFC3339 string                          |
| timelib          | `is_before(timestamp1, timestamp2)`                                                 | Check if the first timestamp is before the second                      |
| timelib          | `is_after(timestamp1, timestamp2)`                                                  | Check if the first timestamp is after the second                       |
| timelib          | `seconds_since(timestamp1, timestamp2)`                                             | Get the number of seconds between two timestamps                       |
| timelib          | `minutes(n)` / `hours(n)` / `days(n)`                                               | Convert time intervals to seconds                                      |
| entitylib        | `get_user(user_id)`                                                                 | Look up a user by ID                                                   |
| entitylib        | `get_group(group_id)`                                                               | Look up a group by ID                                                  |
| entitylib        | `get_resource(resource_id)`                                                         | Look up a resource by ID                                               |
| ticketslib       | `providers.<PROVIDER>`                                                              | Access an installed ticket provider (e.g. `ticketslib.providers.JIRA`) |
| ticketslib       | `list_projects(provider)`                                                           | List projects on a provider; returns a dict keyed by project key       |
| ticketslib       | `create_ticket(project, title, description)`                                        | Create a ticket on the provider; returns a ticket object               |
| ticketslib       | `get_ticket(provider, remote_ticket_id)`                                            | Fetch an existing ticket by its remote identifier                      |
| ticketslib       | `comment_ticket(provider, remote_ticket_id, comment)`                               | Add a comment to an existing ticket                                    |
| ticketslib       | `close_ticket(provider, remote_ticket_id, [comment])`                               | Close a ticket, with an optional closing comment                       |

### Request Review Functions

| Module  | Function                                      | Description                                                                                                                |
| ------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| context | `get_request()`                               | Get the request being reviewed                                                                                             |
| actions | `approve([comment])`                          | Approve the request                                                                                                        |
| actions | `deny(comment)`                               | Deny the request (comment required)                                                                                        |
| actions | `comment(comment)`                            | Add a comment                                                                                                              |
| actions | `pause(minutes)`                              | Pause script execution for 1–1440 minutes, then resume from the same point; actions before the pause are skipped on replay |
| actions | `poll(pollFunction, minutes, max_iterations)` | Call `pollFunction` every `minutes` minutes (1–1440) up to `max_iterations` times (1–50); returns `True` if it succeeded   |

### Request Attributes

| Attribute                    | Type   | Always Present     |
| ---------------------------- | ------ | ------------------ |
| `id`                         | String | Yes                |
| `reason`                     | String | Yes                |
| `requester_id`               | String | Yes                |
| `status`                     | String | Yes                |
| `target_user_id`             | String | No                 |
| `target_group_id`            | String | No                 |
| `requested_duration_minutes` | int    | No                 |
| `requested_resources`        | List   | Yes (may be empty) |
| `requested_groups`           | List   | Yes (may be empty) |
| `custom_fields`              | Dict   | Yes (may be empty) |
