Skip to main content
Facts represent your application’s authorization data in Oso Cloud.
This page shows how to insert facts manually or at runtime using the API, SDKs, or CLI.
Use this pattern when:
  • Testing or iterating on your policy in development.
  • Adding or updating roles, relationships, or attributes during runtime.
  • Keeping facts up-to-date in production with the Batch API.
  • Performing small- to medium-sized inserts (for large-scale sync, see Sync facts).

Insert facts in development

You can quickly add or remove facts when testing your policy.

Oso Cloud UI

Use the Fact Schema in the Oso Cloud UI to quickly add or remove facts when testing or iterating on your policy. The Fact Schema lists all fact types referenced in your policy; these are the types Oso Cloud expects you to send. Add a fact: Click + Add next to a fact type.
Remove a fact: Click ▼ Show matching facts, then Delete next to the fact.

CLI

# Give alice the admin role on org:acme
oso-cloud tell has_role User:alice admin Org:acme

SDKs

# Python
oso.insert(("has_role", User("alice"), "admin", Org("acme")))
// Node.js
await oso.insert(["has_role", {type: "User", id: "alice"}, "admin", {type: "Org", id: "acme"}]);
See SDK references for full method signatures.

Insert facts at runtime

When your application creates or updates data, insert facts to reflect the new state. Example code below:
from oso_cloud import Value

# Insert a single fact
oso.insert((
  "has_role", 
  Value("User", "bob"), 
  "owner", 
  Value("Organization", "acme")
))

# Insert with variables for reuse
user = Value("User", "alice")
repo = Value("Repository", "anvils")
oso.insert(("has_role", user, "maintainer", repo))

Add and remove facts with Batch

Whenever you insert, update, or delete authorization-relevant data in your application, you should mirror that change in Oso Cloud using the Batch API. This keeps your authorization facts consistent with your application state. The dual-writes approach is similar to updating a search index: Oso Cloud maintains an index of authorization data that your policy evaluates against. For example, when creating a new resource, send facts that represent its relationships and roles:
def create_repository(org_id):
    org = Organization(org_id)
    repo = Repository(payload["name"], org)

    # Persist the repository to the database
    session.add(repo)

    # Send facts to Oso Cloud
    with oso.batch() as tx:
        # The parent organization of `repo` is `org`
        tx.insert(("has_relation", repo, "organization", org))
        # The current user gets the `admin` role on the new `repo`
        tx.insert(("has_role", current_user, "admin", repo))

    # Commit once Oso Cloud is updated
    session.commit()

    return repo.as_json(), 201
When deleting a resource, remove the corresponding facts:
with oso.batch() as tx:
    # Remove all `has_relation` facts for the repository
    tx.delete(("has_relation", repo, None, None))
    # Remove all `has_role` facts for the repository
    tx.delete(("has_role", None, None, repo))

Best practices

  • Prefer batch APIs for multiple inserts.
  • Use descriptive predicates like “has_role”, “is_banned”, or “has_relation”. -Avoid inserts for ephemeral data (e.g. request time, IP). Use context facts instead.
  • Test your facts in the Explain tab to verify behavior.