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

# Grants & permissions

> The scope-native access primitive — a wallet-signed, onchain, revocable grant.

A **grant** is a signed permission that lets a builder access specific [scopes](/protocol-reference/scopes-schemas) of a user's data. Grants are the access-control primitive of the protocol — no builder can read data without one, and every grant can be revoked by the user at any time.

The grant is **scope-native onchain**: the onchain record carries the **scopes** and an **expiry** directly, so the chain expresses exactly what the [Context Gateway](/applications/context-gateway) and the [Personal Server](/protocol-reference/personal-servers) enforce — without resolving file IDs off-chain.

Granularity is the point. A grant is scoped to **specific data types, not a whole account** — a user can share `spotify.listening_history` without exposing their messages — and is **time-bounded and revocable**, so consent stays narrow and reversible instead of an all-or-nothing login. The same primitive is designed to extend beyond "read this scope" to **"run this specific operation over this subset of data"** — authorizing a computation rather than raw access (see [Operation-scoped grants](#operation-scoped-grants) below).

Grants can also carry economics. Rather than a one-off read, a user can grant a [DataDAO / DLP](/applications/confidential-compute) the right to make decisions over their contributed data, and in return receive a **VRC-20 token** representing **proportional rights over the pooled dataset** — turning a permission into an ongoing stake in how that data is used and monetized.

## How grants work

1. A builder requests a set of scopes (e.g. `instagram.profile`, `spotify.listening_history`)
2. The user reviews the request and approves it in their app
3. The user's wallet signs the grant (EIP-712), binding the grantee, the scopes, and an expiry
4. The grant is recorded through the [DP RPC](/protocol-reference/dp-rpc) and anchored onchain
5. On every data request, the Personal Server checks the grant before releasing data

## Requesting a grant (the Connect flow)

A builder does not implement grant signing itself. It asks the [Vana SDK](/applications/context-gateway#the-sdk) to create an **access request**; the user is sent to a Vana approval surface, signs the grant there, and the builder polls for the approved result:

1. The builder's backend calls `createAccessRequest`, which returns an `approvalUrl` and a `requestId`.
2. The user opens the approval surface (a browser tab), reviews the app, source, and scopes, and approves — signing the grant with their wallet.
3. The builder polls `getAccessRequestStatus(requestId)` until it resolves to `approved`, which returns the `grantId`, the user's `personalServerUrl`, and the granted scope.
4. The builder reads the approved data from the Personal Server, paying the protocol fee from escrow — see [Payments & fees](/protocol-reference/payments-fees).

<Tip>For the end-to-end integration — SDK setup, backend routes, and a React button — follow the [Build a Vana App](/build-a-vana-app) guide.</Tip>

## Grant format (EIP-712)

Grants use EIP-712 typed data so consent is cryptographically verifiable.

```typescript theme={null}
const grantTypedData = {
  domain: {
    name: "Vana Data Portability",
    version: "2",
    chainId: 14800,
    verifyingContract: "0x...", // DataPortabilityPermissions (V2)
  },
  types: {
    Grant: [
      { name: "grantor", type: "address" },
      { name: "granteeId", type: "bytes32" },
      { name: "scopes", type: "string[]" },
      { name: "expiresAt", type: "uint256" },
      { name: "nonce", type: "uint256" },
    ],
  },
  primaryType: "Grant",
  message: {
    grantor: "0x...",                 // User's wallet address
    granteeId: "0x...",               // Builder's grantee id
    scopes: ["instagram.profile"],    // The unit of access
    expiresAt: 0,                     // 0 = no expiration
    nonce: 1,                         // Replay protection
  },
};
```

| Field       | Description                                                          |
| ----------- | -------------------------------------------------------------------- |
| `grantor`   | The user granting access                                             |
| `granteeId` | The builder receiving access (registered in DataPortabilityGrantees) |
| `scopes`    | Scope identifiers the grant covers — the unit of access              |
| `expiresAt` | Unix timestamp for expiration; `0` means it never expires            |
| `nonce`     | Monotonically increasing value per user, prevents replay             |

<Info>The example uses `expiresAt: 0` (never expires) to show the case some integrations want — standing consent for a service the user keeps connected. For most grants, prefer a real expiry: a bounded `expiresAt` limits how long a single approval stays live, and is the safer default.</Info>

## Grant lifecycle

```mermaid theme={null}
stateDiagram-v2
    classDef active fill:#E2F4DC,stroke:#34A853,color:#14431f
    classDef revoked fill:#FFE0E0,stroke:#E53935,color:#5a1212
    classDef expired fill:#EEF1F5,stroke:#9AA4B2,color:#1f2937

    [*] --> Active: create (user signs)
    Active --> Revoked: user revokes
    Active --> Expired: expiresAt passes
    Revoked --> [*]
    Expired --> [*]

    class Active active
    class Revoked revoked
    class Expired expired
```

* **Create** — the user signs; the grant is recorded and anchored.
* **Active** — the grantee may read covered scopes until expiry or revocation.
* **Revoked** — the user revokes at any time. Enforcement has two layers: where the **Context Gateway** serves data, it stops serving **immediately**, even before onchain confirmation, while the revocation is **anchored on-chain** as the durable record. Integrations that bypass the Context Gateway enforce against that onchain state.
* **Expired** — once `expiresAt` passes, the grant stops authorizing reads.

## Verification

When a builder makes a data request, the Personal Server verifies the grant before serving data:

1. **Registered** — the requester is a registered builder
2. **Not revoked** — the grant has not been revoked
3. **Not expired** — `expiresAt` is `0` or in the future
4. **Scope match** — the requested scope is within the granted scopes
5. **Signer match** — the request recovers to the builder that matches the grant's grantee
6. **Fee paid** — the grant's fee shows as paid (see [Payments & fees](/protocol-reference/payments-fees))

If any check fails, the Personal Server returns an error:

| Code  | Meaning                           |
| ----- | --------------------------------- |
| `401` | Invalid signature or unauthorized |
| `403` | Valid auth but not permitted      |
| `410` | Grant revoked                     |
| `411` | Grant expired                     |
| `412` | Scope not granted                 |

## Operation-scoped grants

Every grant today authorizes one implicit operation: **return the scope** — the grantee reads the covered data in plaintext. The designed extension is a grant that instead carries an **operations pipeline**: the user authorizes a specific computation over their data, the [Personal Server](/protocol-reference/personal-servers) decrypts the data and executes that pipeline locally, and the grantee receives **only the result — never the raw data**.

The consent moment changes accordingly. Instead of

> *"App X requests access to your Instagram posts"*

the user approves

> *"App X requests access to your **anonymized** Instagram posts"*

— or a summary, an aggregate, a redaction: whatever the pipeline the grant names actually produces.

This is what an application should reach for when it wants a **privacy-preserving operation over a user's data** — an LLM summary of a user's chat history, say — where the application only needs the output, not the records themselves.

Everything else about the grant stays as described above: the same EIP-712 format (plus the operations field), the same lifecycle, the same verification on the Personal Server, the same fee gating. The one piece expected to evolve with it is **pricing** — fees for an operation-scoped grant may need to be dynamic, reflecting the compute the pipeline requires, rather than a flat per-access fee.

<Info>**Status.** Operation-scoped grants are a **design direction, not implemented** — today every grant returns the scope's data directly. Note the distinction from [Confidential compute](/applications/confidential-compute): operation-scoped grants run a computation on **one user's data, on that user's own Personal Server**; confidential compute runs jobs over **pooled data from many users** in a TEE network.</Info>

## Onchain record

The permissions contract emits a single event capturing the grant's substance whenever it is created or re-issued:

```solidity theme={null}
event PermissionSet(
    bytes32  indexed id,
    address  indexed grantorAddress,
    bytes32  indexed granteeId,
    string[] scopes,
    uint256  grantVersion,
    uint256  expiresAt
);
```

Because `scopes` and `expiresAt` live in the event itself, anyone can reconstruct who may access what, until when, directly from the chain — without resolving file IDs off-chain.

This is a deliberate choice, modelled on how public blockchains already work: just as a token transfer publicly shows *this address sent this asset to that address*, a grant publicly shows *this address shared this kind of data with this grantee, until when* — the transparency model the industry has broadly adopted. For deployments that prefer not to expose scope details on-chain, commitments or hashed scopes are available as an option.

<Info>**Status.** Grant signing, verification, and revocation work end to end. The scope-native permissions contract (V2, `DataPortabilityPermissions`) is the current model; a previous file-based permission contract remains deployed on mainnet during migration. See [Core contracts](/network/smart-contracts-addresses) for addresses.</Info>

## Related

* [Personal Servers](/protocol-reference/personal-servers) — where grants are enforced
* [Payments & fees](/protocol-reference/payments-fees) — how a grant's fee is funded and settled
* [Scopes & schemas](/protocol-reference/scopes-schemas) — what scopes are and how they're defined
* [Protocol — DP RPC](/protocol-reference/dp-rpc) — identity and the settlement path
* [Build a Vana App](/build-a-vana-app) — the end-to-end builder integration
