> ## 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.

# Send data as context facts

# Send Data to Oso Cloud as Context Facts

For Oso to make authorization decisions, it requires data from your
application. Oso accepts data as
[facts](/develop/facts/overview) -- a lightweight
format that complements logic written in Polar.

You send facts to Oso Cloud along with an authorization request. Facts sent to Oso Cloud with this method are [context
facts](/develop/facts/context-facts). The syntax depends on which [client
SDK](/reference/sdks/overview) you use.
In the TypeScript SDK, context facts are passed as an optional 4th argument to the `oso.authorize` call.

```typescript src/authz.ts focus=31-57,64 theme={null}
import { UserWithRoles } from "../authn";
import { Repository } from "@prisma/client";
import { Oso } from "oso-cloud";

// Make sure the API key is defined and instantiate the client
if (!process.env.OSO_API_KEY) {
  throw "Missing OSO API key from environment";
}

const oso_url = process.env.OSO_URL
  ? process.env.OSO_URL
  : "https://cloud.osohq.com";
const osoClient = new Oso(oso_url, process.env.OSO_API_KEY);

// A user can read a repo if they have any role on the repo or its parent organization.
export async function canReadRepo(
  user: UserWithRoles,
  repo: Repository,
): Promise<boolean> {
  const orgRole = user.orgRoles.some((orgRole) => orgRole.orgId == repo.orgId);
  const repoRole = user.repoRoles.some(
    (repoRole) => repoRole.repoId == repo.id,
  );

  const authorizedInline = orgRole || repoRole;

  // entities for Oso
  const osoUser = { type: "User", id: user.id.toString() };
  const osoRepo = { type: "Repository", id: repo.id.toString() };
  const osoOrg = { type: "Organization", id: repo.orgId.toString() };

  // get roles for context facts
  const osoOrgRole = user.orgRoles
    .filter((orgRole) => orgRole.orgId == repo.orgId)
    .pop();
  const osoRepoRole = user.repoRoles
    .filter((repoRole) => repoRole.repoId == repo.id)
    .pop();

  // define context facts
  let contextFacts: [
    string,
    { type: string; id: string },
    string,
    { type: string; id: string },
  ][] = [
    // fact format: has_relation(Repository: repoId, "parent", Organization: orgId)
    ["has_relation", osoRepo, "parent", osoOrg],
  ];
  if (osoOrgRole) {
    // has_role(User: userId, role, Organization: orgId)
    contextFacts.push(["has_role", osoUser, osoOrgRole.role, osoOrg]);
  }
  if (osoRepoRole) {
    // has_role(User: userId, role, Repository: repoId)
    contextFacts.push(["has_role", osoUser, osoRepoRole.role, osoRepo]);
  }

  // authorize using oso.authorize
  const authorizedOso = await osoClient.authorize(
    osoUser,
    "read",
    osoRepo,
    contextFacts,
  );
  console.log(
    `User:${user.id} read Repository:${repo.id}: inline: ${authorizedInline}; Oso: ${authorizedOso}`,
  );

  return authorizedInline;
}
```

Code defining context facts build an array of up to three facts.

* A fact declaring the relationship between the `Repository` and its parent `Organization`
  ```typescript theme={null}
  ["has_relation", osoRepo, "parent", osoOrg];
  ```
* \[Optional] A fact declaring the `User`'s role in the `Organization`
  ```typescript theme={null}
  ["has_role", osoUser, osoOrgRole.role, osoOrg];
  ```
* \[Optional] A fact declaring the `User`'s role on the `Repository`
  ```typescript theme={null}
  ["has_role", osoUser, osoRepoRole.role, osoRepo];
  ```

The array is passed as the fourth argument to `.authorize()`.

```typescript theme={null}
const authorizedOso = await osoClient.authorize(
  osoUser,
  "read",
  osoRepo,
  contextFacts, // <--- Context facts provided to .authorize()
);
```

Now the results from Oso Cloud are the same as the results from the original code.

```console focus=2,6 theme={null}
backend  | User:1 read Repository:1: inline: false; Oso: false
backend  | User:1 read Repository:2: inline: true; Oso: true
backend  | User:1 read Repository:3: inline: false; Oso: false
backend  | User:1 read Repository:4: inline: false; Oso: false
backend  | User:1 read Repository:5: inline: false; Oso: false
backend  | User:1 read Repository:6: inline: true; Oso: true
backend  | User:1 read Repository:7: inline: false; Oso: false
backend  | User:1 read Repository:8: inline: false; Oso: false
backend  | User:1 read Repository:9: inline: false; Oso: false
backend  | User:1 read Repository:10: inline: false; Oso: false
```

Learn more about the [limitations](/reference/polar/types#fact-argument-length-limit) of facts in the primitive types section of our documentation.

Context facts provide your authorization data to Oso Cloud conveniently. You send it whenever you make a authorization request.

However, over time this generates additional network traffic as you make more requests. Much of that traffic is unnecessary, because these data do not change frequently.

Local Authorization informs the Oso Cloud client how to translate data from your application database directly into facts to make an authorization decision.

Learn to [set that up next](/learn/guides/adopt-local-authorization/replace-with-local-authorization).
