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

# Authorization Checks

> Enforce permissions in your app.

## Authorize

Check if an actor is allowed to perform an action on a specific resource.

**Node.js**

```javascript theme={null}
// Basic authorization check
const authorized = await oso.authorize(alice, "read", anvilsRepository);
if (!authorized) {
  throw new Error("Access denied");
}

// With context facts for additional information
const authorized = await oso.authorize(
  alice, 
  "read", 
  issue, 
  [["has_relation", issue, "parent", anvilsRepository]]  // Context facts
);

console.log(`Access ${authorized ? 'granted' : 'denied'}`);
```

**Signature:** `oso.authorize(actor, action, resource, contextFacts?)`

```python theme={null}
# Basic authorization check
if not oso.authorize(alice, "read", anvils_repository):
    raise Exception("Action is not allowed")

# With context facts
authorized = oso.authorize(
    alice, 
    "read", 
    anvils_repository, 
    context_facts=[("has_relation", issue_on_anvils_repository, "parent", anvils_repository)]
)

print(f"Access {'granted' if authorized else 'denied'}")
```

**Signature:** `oso.authorize(actor, action, resource, context_facts=None)`

```go theme={null}
// Basic authorization check
allowed, err := osoClient.Authorize(user, "read", anvilsRepository)
if err != nil {
    log.Fatal(err)
}
if !allowed {
    return fmt.Errorf("access denied")
}

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_relation", issueOnAnvilsRepository, oso.String("parent"), anvilsRepository),
}
allowed, err = osoClient.AuthorizeWithContext(user, "read", issueOnAnvilsRepository, contextFacts)
```

**Signature:** `osoClient.Authorize(actor, action, resource)` | `osoClient.AuthorizeWithContext(actor, action, resource, contextFacts)`

```java theme={null}
// Basic authorization check
boolean allowed = oso.authorize(user, "read", anvilsRepository);
if (!allowed) {
    throw new SecurityException("Access denied");
}

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_relation", Arrays.asList(issueOnAnvilsRepository, new Value("parent"), anvilsRepository))
);
boolean allowed = oso.authorize(user, "read", issueOnAnvilsRepository, contextFacts);
```

**Signature:** `oso.authorize(actor, action, resource, contextFacts?)`

```ruby theme={null}
# Basic authorization check
raise "Action is not allowed" unless oso.authorize(alice, "read", anvils_repository)

# With context facts
authorized = oso.authorize(
  alice, 
  "read", 
  anvils_repository, 
  context_facts: [["has_relation", issue_on_anvils_repository, "parent", anvils_repository]]
)

puts authorized ? "Access granted" : "Access denied"
```

**Signature:** `oso.authorize(actor, action, resource, context_facts=nil)`

```csharp theme={null}
// Basic authorization check
var allowed = await oso.Authorize(user, "read", anvilsRepository);
if (!allowed) {
    throw new UnauthorizedAccessException("Access denied");
}

// With context facts
var contextFacts = new List<Fact> { 
    new Fact("has_relation", new List<Value> { 
        issueOnAnvilsRepository, 
        new Value("String", "parent"), 
        anvilsRepository 
    })
};
var allowed = await oso.Authorize(user, "read", anvilsRepository, contextFacts);
```

**Signature:** `oso.Authorize(actor, action, resource, contextFacts?)`

**CLI**

```bash theme={null}
# Basic authorization check
oso-cloud authorize User:bob read Repository:anvils

# With context facts
oso-cloud authorize \
  -c "has_relation Issue:issueOnAnvilsRepository parent Repository:anvils" \
  User:bob read Issue:issueOnAnvilsRepository
```

**Signature:** `oso-cloud authorize <actor> <action> <resource>`

## List Resources

Get all resource IDs that an actor can perform an action on.

**Node.js**

```javascript theme={null}
// List all repositories the user can read
const repositoryIds = await oso.list(alice, "read", "Repository");
console.log("Readable repositories:", repositoryIds);

// With context facts
const issueIds = await oso.list(
  alice, 
  "read", 
  "Issue",
  [
    ["has_relation", issueOnAnvilsRepository, "parent", anvilsRepository],
    ["has_relation", issueOnAcmeRepository, "parent", acmeRepository]
  ]
);
```

**Signature:** `oso.list(actor, action, resourceType, contextFacts?)`

```python theme={null}
# List all repositories the user can read
repository_ids = oso.list(alice, "read", "Repository")
print(f"Readable repositories: {repository_ids}")

# With context facts
issue_ids = oso.list(
    alice, 
    "read", 
    "Issue",
    context_facts=[
        ("has_relation", issue_on_anvils_repository, "parent", anvils_repository),
        ("has_relation", issue_on_acme_repository, "parent", acme_repository)
    ]
)
```

**Signature:** `oso.list(actor, action, resource_type, context_facts=None)`

```go theme={null}
// List all repositories the user can read
repositoryIds, err := osoClient.List(user, "read", "Repository", nil)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Readable repositories: %v\n", repositoryIds)

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_relation", issueOnAnvilsRepository, oso.String("parent"), anvilsRepository),
    oso.NewFact("has_relation", issueOnAcmeRepository, oso.String("parent"), acmeRepository),
}
issueIds, err := osoClient.ListWithContext(user, "read", "Issue", contextFacts)
```

**Signature:** `osoClient.List(actor, action, resourceType, nil)` | `osoClient.ListWithContext(actor, action, resourceType, contextFacts)`

```java theme={null}
// List all repositories the user can read
String[] repositoryIds = oso.list(user, "read", "Repository");
System.out.println("Readable repositories: " + Arrays.toString(repositoryIds));

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_relation", Arrays.asList(issueOnAnvilsRepository, new Value("parent"), anvilsRepository)),
    new Fact("has_relation", Arrays.asList(issueOnAcmeRepository, new Value("parent"), acmeRepository))
);
String[] issueIds = oso.list(user, "read", "Issue", contextFacts);
```

**Signature:** `oso.list(actor, action, resourceType, contextFacts?)`

```ruby theme={null}
# List all repositories the user can read
repository_ids = oso.list(alice, "read", "Repository")
puts "Readable repositories: #{repository_ids}"

# With context facts
issue_ids = oso.list(
  alice, 
  "read", 
  "Issue",
  context_facts: [
    ["has_relation", issue_on_anvils_repository, "parent", anvils_repository],
    ["has_relation", issue_on_acme_repository, "parent", acme_repository]
  ]
)
```

**Signature:** `oso.list(actor, action, resource_type, context_facts=nil)`

```csharp theme={null}
// List all repositories the user can read
var repositoryIds = await oso.List(user, "read", "Repository");
Console.WriteLine($"Readable repositories: {string.Join(", ", repositoryIds)}");

// With context facts (contextFacts parameter not shown in docs.json for .NET list)
```

**Signature:** `oso.List(actor, action, resourceType)`

**CLI**

```bash theme={null}
# List all repositories the user can read
oso-cloud list User:bob read Repository

# With context facts
oso-cloud list \
  -c "has_relation Issue:issueOnAnvilsRepository parent Repository:anvils" \
  -c "has_relation Issue:issueOnAcmeRepository parent Repository:acme" \
  User:bob read Issue
```

**Signature:** `oso-cloud list <actor> <action> <resource-type>`

## List Resources (Paginated)

Paginate through resource IDs that an actor can perform an action on. Use this when you need control over page size or want to handle large result sets incrementally. `page_size` is a required parameter.

**Node.js**

```javascript theme={null}
// Fetch the first page
const firstPage = await oso.listPaginated(alice, "read", "Repository", 10000);
console.log("First page:", firstPage.results);

// Fetch subsequent pages using the nextPageToken
if (firstPage.nextPageToken) {
  const secondPage = await oso.listPaginated(
    alice,
    "read",
    "Repository",
    10000,
    firstPage.nextPageToken
  );
  console.log("Second page:", secondPage.results);
}
```

**Signature:** `oso.listPaginated(actor, action, resourceType, pageSize, pageToken?, contextFacts?)`

**Returns:** `{ results: string[], nextPageToken: string | null }`

```python theme={null}
# Fetch the first page
first_page = oso.list_paginated(alice, "read", "Repository", page_size=10000)
print(f"First page: {first_page.results}")

# Fetch subsequent pages using the next_page_token
if first_page.next_page_token:
    second_page = oso.list_paginated(
        alice,
        "read",
        "Repository",
        page_size=10000,
        page_token=first_page.next_page_token
    )
    print(f"Second page: {second_page.results}")
```

**Signature:** `oso.list_paginated(actor, action, resource_type, page_size, page_token=None, context_facts=None)`

**Returns:** `ListResult` with `.results` and `.next_page_token`

```go theme={null}
// Fetch the first page
firstPage, err := osoClient.ListPaginated(user, "read", "Repository", 10000, nil)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("First page: %v\n", firstPage.Results)

// Fetch subsequent pages using the NextPageToken
if firstPage.NextPageToken != nil {
    secondPage, err := osoClient.ListPaginated(
        user, "read", "Repository", 10000, firstPage.NextPageToken,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Second page: %v\n", secondPage.Results)
}
```

**Signature:** `osoClient.ListPaginated(actor, action, resourceType, pageSize, pageToken)` | `osoClient.ListPaginatedWithContext(actor, action, resourceType, pageSize, pageToken, contextFacts)`

**Returns:** `*ListPage` with `.Results` and `.NextPageToken`

```java theme={null}
// Fetch the first page
ListPage firstPage = oso.listPaginated(user, "read", "Repository", 10000, null);
System.out.println("First page: " + Arrays.toString(firstPage.results));

// Fetch subsequent pages using the nextPageToken
if (firstPage.nextPageToken != null) {
    ListPage secondPage = oso.listPaginated(
        user, "read", "Repository", 10000, firstPage.nextPageToken
    );
    System.out.println("Second page: " + Arrays.toString(secondPage.results));
}
```

**Signature:** `oso.listPaginated(actor, action, resourceType, pageSize, pageToken)` | `oso.listPaginated(actor, action, resourceType, pageSize, pageToken, contextFacts)`

**Returns:** `ListPage` with `.results` and `.nextPageToken`

```ruby theme={null}
# Fetch the first page
first_page = oso.list_paginated(alice, "read", "Repository", 10000)
puts "First page: #{first_page.results}"

# Fetch subsequent pages using the next_page_token
if first_page.next_page_token
  second_page = oso.list_paginated(
    alice,
    "read",
    "Repository",
    10000,
    page_token: first_page.next_page_token
  )
  puts "Second page: #{second_page.results}"
end
```

**Signature:** `oso.list_paginated(actor, action, resource_type, page_size, page_token: nil, context_facts: [])`

**Returns:** `ListResult` with `.results` and `.next_page_token`

```csharp theme={null}
// Fetch the first page
var firstPage = await oso.ListPaginated(user, "read", "Repository", 10000, null);
Console.WriteLine($"First page: {string.Join(", ", firstPage.Results)}");

// Fetch subsequent pages using the NextPageToken
if (firstPage.NextPageToken != null) {
    var secondPage = await oso.ListPaginated(
        user, "read", "Repository", 10000, firstPage.NextPageToken
    );
    Console.WriteLine($"Second page: {string.Join(", ", secondPage.Results)}");
}
```

**Signature:** `oso.ListPaginated(actor, action, resourceType, pageSize, pageToken)` | `oso.ListPaginated(actor, action, resourceType, pageSize, pageToken, contextFacts)`

**Returns:** `ListResult` with `.Results` and `.NextPageToken`

## Get Actions

Get all actions an actor can perform on a specific resource.

**Node.js**

```javascript theme={null}
// Get all actions user can perform on repository
const actions = await oso.actions(user, acmeRepository);
console.log("Available actions:", actions);

// With context facts
const actions = await oso.actions(
  alice, 
  issueOnAcmeRepository, 
  [["has_relation", issueOnAcmeRepository, "parent", acmeRepository]]
);
```

**Signature:** `oso.actions(actor, resource, contextFacts?)`

```python theme={null}
# Get all actions user can perform on repository
actions = oso.actions(alice, acme_repository)
print(f"Available actions: {actions}")

# With context facts
actions = oso.actions(
    alice, 
    issue_on_acme_repository, 
    context_facts=[("has_relation", issue_on_acme_repository, "parent", acme_repository)]
)
```

**Signature:** `oso.actions(actor, resource, context_facts=None)`

```go theme={null}
// Get all actions user can perform on repository
actions, err := osoClient.Actions(user, anvilsRepository)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Available actions: %v\n", actions)

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_relation", issueOnAnvilsRepository, oso.String("parent"), anvilsRepository),
}
actions, err = osoClient.ActionsWithContext(user, issueOnAnvilsRepository, contextFacts)
```

**Signature:** `osoClient.Actions(actor, resource)` | `osoClient.ActionsWithContext(actor, resource, contextFacts)`

```java theme={null}
// Get all actions user can perform on repository
String[] actions = oso.actions(user, anvilsRepository);
System.out.println("Available actions: " + Arrays.toString(actions));

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_relation", Arrays.asList(issueOnAnvilsRepository, new Value("parent"), anvilsRepository))
);
String[] actions = oso.actions(user, issueOnAnvilsRepository, contextFacts);
```

**Signature:** `oso.actions(actor, resource, contextFacts?)`

```ruby theme={null}
# Get all actions user can perform on repository
actions = oso.actions(alice, acme_repository)
puts "Available actions: #{actions}"

# With context facts
actions = oso.actions(
  alice, 
  issue_on_acme_repository, 
  context_facts: [["has_relation", issue_on_acme_repository, "parent", acme_repository]]
)
```

**Signature:** `oso.actions(actor, resource, context_facts=nil)`

```csharp theme={null}
// Get all actions user can perform on repository
var actions = await oso.Actions(user, anvilsRepository);
Console.WriteLine($"Available actions: {string.Join(", ", actions)}");

// Context facts not shown in docs.json for .NET actions
```

**Signature:** `oso.Actions(actor, resource)`

**CLI**

```bash theme={null}
# Get all actions user can perform on repository
oso-cloud actions User:bob Repository:anvils

# With context facts
oso-cloud actions \
  -c "has_relation Issue:issueOnAnvilsRepository parent Repository:anvils" \
  User:bob Issue:issueOnAnvilsRepository
```

**Signature:** `oso-cloud actions <actor> <resource>`

## Authorize Multiple Resources

Check authorization for multiple resources at once for better performance.

**Ruby**

```ruby theme={null}
# Check multiple resources at once
resources = oso.authorize_resources(
  alice, 
  "read", 
  [anvils_repository, acme_repository]
)
puts "Authorized resources: #{resources}"

# With context facts
authorized_resources = oso.authorize_resources(
  alice, 
  "read", 
  [issue_on_anvils_repository, issue_on_acme_repository],
  context_facts: [
    ["has_relation", issue_on_anvils_repository, "parent", anvils_repository],
    ["has_relation", issue_on_acme_repository, "parent", acme_repository]
  ]
)
```

**Signature:** `oso.authorize_resources(actor, action, resources, context_facts=nil)`

```csharp theme={null}
// Check multiple resources at once
var results = await oso.AuthorizeResources(
  user, 
  "read", 
  new List<Value> { anvilsRepository, acmeRepository }
);
Console.WriteLine($"Authorized resources: {string.Join(", ", results)}");

// With context facts
var contextFacts = new List<Fact> { contextFact1, contextFact2 };
var results = await oso.AuthorizeResources(
  user, 
  "read", 
  new List<Value> { anvilsRepository, acmeRepository }, 
  contextFacts
);
```

**Signature:** `oso.AuthorizeResources(actor, action, resources, contextFacts?)`

**CLI**

```bash theme={null}
# Check multiple resources at once
oso-cloud authorize-resources User:bob read Repository:anvils Repository:acme

# With context facts
oso-cloud authorize-resources \
  -c "has_relation Issue:issueOnAnvilsRepository parent Repository:anvils" \
  -c "has_relation Issue:issueOnAcmeRepository parent Repository:acme" \
  User:bob read Issue:issueOnAnvilsRepository Issue:issueOnAcmeRepository
```

**Signature:** `oso-cloud authorize-resources <actor> <action> (<resource>)*`

## Query Builder

Build complex queries with additional constraints and evaluate them flexibly.

**Node.js**

```javascript theme={null}
// Basic query building
const query = oso.buildQuery(["allow", actor, "read", repository]);
const result = await query.evaluate(repository);

// Add constraints with 'and'
const constrainedQuery = oso.buildQuery(["allow", actor, "read", repository])
  .and(["has_relation", repository, "folder", folder]);

// Filter with 'in' clause
const filteredQuery = oso.buildQuery(["allow", actor, action, repository])
  .in(repository, repositories);

// Add context facts
const contextQuery = oso.buildQuery(["allow", actor, "read", repository])
  .withContextFacts([["has_role", actor, "owner", repo]]);

// Different evaluation modes
const exists = await query.evaluate();                           // Boolean
const actions = await query.evaluate(action);                    // Single variable
const pairs = await query.evaluate([action, repository]);        // Tuple variables
const mapped = await query.evaluate(new Map([[repository, action]])); // Map
```

**Signature:** `oso.buildQuery([predicate, ...args])`

```python theme={null}
# Basic query building
query = oso.build_query(("allow", actor, "read", repository))
result = query.evaluate(repository)

# Add constraints with 'and_'
constrained_query = oso.build_query(("allow", actor, "read", repository)) \
    .and_(("has_relation", repository, "folder", folder))

# Filter with 'in_' clause
filtered_query = oso.build_query(("allow", actor, action, repository)) \
    .in_(repository, repositories)

# Add context facts
context_query = oso.build_query(("allow", actor, "read", repository)) \
    .with_context_facts([("has_role", actor, "owner", repo)])

# Different evaluation modes
exists = query.evaluate()                              # Boolean
actions = query.evaluate(action)                       # Single variable
pairs = query.evaluate((action, repository))           # Tuple variables
mapped = query.evaluate({repository: action})          # Dictionary
```

**Signature:** `oso.build_query((predicate, *args))`

```go theme={null}
// Basic query building
query := osoClient.BuildQuery(oso.NewQueryFact("allow", actor, oso.String("read"), repository))
repos, err := query.EvaluateValues(repository)

// Add constraints with 'And'
constrainedQuery := osoClient.BuildQuery(oso.NewQueryFact("allow", actor, oso.String("read"), repository)).
    And(oso.NewQueryFact("has_relation", repository, oso.String("folder"), folder))

// Filter with 'In' clause
filteredQuery := osoClient.BuildQuery(oso.NewQueryFact("allow", actor, action, repository)).
    In(repository, repositories)

// Add context facts
contextQuery := osoClient.BuildQuery(oso.NewQueryFact("allow", actor, oso.String("read"), repository)).
    WithContextFacts([]oso.Fact{oso.NewFact("has_role", actor, oso.String("owner"), repo)})

// Different evaluation modes
allowed, err := query.EvaluateExists()                                    // Boolean
actions, err := query.EvaluateValues(action)                             // Values for variable
pairs, err := query.EvaluateCombinations([]oso.Variable{action, repo})   // Variable combinations
err = query.Evaluate(&repoActions, map[oso.Variable]oso.Variable{repository: action}) // Custom mapping
```

**Signature:** `osoClient.BuildQuery(queryFact)`

```java theme={null}
// Basic query building
QueryBuilder query = oso.buildQuery("allow", actor, action, repository);
List<String> results = query.evaluate(EvaluateArgs.values(repository));

// Add constraints with 'and'
QueryBuilder constrainedQuery = oso.buildQuery("allow", actor, action, repository)
    .and("has_relation", repository, new Value("folder"), folder);

// Filter with 'in' clause
QueryBuilder filteredQuery = oso.buildQuery("allow", actor, actionVar, repositoryVar)
    .in(repositoryVar, repositoryIds);

// Add context facts
QueryBuilder contextQuery = oso.buildQuery("allow", actor, action, repository)
    .withContextFacts(contextFacts);

// Different evaluation modes
Boolean allowed = query.evaluate(EvaluateArgs.exists());                           // Boolean
List<String> actions = query.evaluate(EvaluateArgs.values(actionVar));            // Values
Map<String, List<String>> mapped = query.evaluate(                                // Map
    EvaluateArgs.map(repositoryVar, EvaluateArgs.values(actionVar))
);
```

**Signature:** `oso.buildQuery(predicate, ...args)`

**CLI**

```bash theme={null}
# Basic query
oso-cloud query allow User:bob read Repository:_

# Query with wildcards
oso-cloud query allow User:admin read _

# With context facts
oso-cloud query \
  -c "has_permission User:bob write Repository:anvils" \
  User:bob write Repository:_
```

**Signature:** `oso-cloud query <predicate> (<actor|resource>)*`

```ruby theme={null}
# Ruby has a simpler query method
results = oso.query("allow", user, "read", OsoCloud::Value.new(type: "Repository"))
admin_results = oso.query("allow", admin_user, "read", nil)

# With context facts
results = oso.query(
  "allow", 
  user, 
  "write", 
  OsoCloud::Value.new(type: "Repository"),
  context_facts: [["has_permission", user, "write", repo]]
)
```

**Signature:** `oso.query(rule, context_facts: nil)`

```csharp theme={null}
// .NET has a simpler query method
var results = await oso.Query("allow", new List<Value> { 
  user, 
  new Value("String", "read"), 
  new Value("Repository", null) 
});

var adminResults = await oso.Query("allow", new List<Value> { 
  admin_user, 
  new Value("String", "read"), 
  new Value(null, null) 
});
```

**Signature:** `oso.Query(rule)`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.