How grants work
- A builder requests access to specific scopes (e.g.
instagram.profile,youtube.watch_history) - The user sees the request and approves or denies it in the Desktop App
- On approval, the Personal Server signs an EIP-712 typed data structure and submits it to the Gateway
- The Gateway returns a
grantId(the onchainpermissionId) and syncs it to the chain asynchronously - The builder uses the
grantIdto make signed requests to the user’s Personal Server
Grant format (EIP-712)
Grants use EIP-712 typed data signatures for cryptographic verifiability.| Field | Description |
|---|---|
user | The user granting access (wallet address) |
builder | The builder receiving access (registered address) |
scopes | Array of scope identifiers the grant covers |
expiresAt | Unix timestamp for expiration; 0 means the grant never expires |
nonce | Monotonically increasing value per user, prevents replay |
grantId returned by the Gateway corresponds to the onchain permissionId in the DataPortabilityPermissions contract.
Grant lifecycle
Create
The user approves a grant request in the Desktop App. The Personal Server:- Calls
POST /v1/grantson itself with{ granteeAddress, scopes, expiresAt?, nonce? } - Signs the EIP-712 typed data with the user’s wallet
- Submits the signed grant to the Gateway (
POST /v1/grants) - The Gateway validates the signature, stores the grant, and returns a
grantId - The grant is synced to the
DataPortabilityPermissionscontract asynchronously
Active
While active, the builder can read data for the granted scopes by including thegrantId in Web3Signed requests to the Personal Server.
Revoked
The user can revoke a grant at any time from the Desktop App. Revocation:- The user signs a revocation
- The Desktop App submits
DELETE /v1/grants/{grantId}to the Gateway - The Gateway marks the grant as revoked immediately
- The revocation is synced to the chain asynchronously
- The Personal Server blocks all future requests using this
grantId
Expired
IfexpiresAt is set and the current time exceeds it, the grant is expired. The Personal Server rejects requests with expired grants.
Verification
When a builder makes a data request, the Personal Server verifies the grant before serving data:- Signature valid — The grant signature matches the claimed user address
- Not revoked — The grant has not been revoked (checked via Gateway or chain)
- Not expired —
expiresAtis0or in the future - Scope match — The requested scope is within the granted scopes
- Signer match — The request’s
Authorizationheader recovers to the builder address that matches the grant’s grantee
| Code | Meaning |
|---|---|
401 | Invalid signature or unauthorized |
403 | Valid auth but not permitted |
410 | Grant revoked |
411 | Grant expired |
412 | Scope not granted |
Connect data flow
The “Connect Data” flow is how users grant a builder access through a web popup and deep link to the Desktop App. It uses the Session Relay service to coordinate between the builder’s web app and the user’s Desktop App.Flow overview
Session states
Session relay API
| Method | Path | Description |
|---|---|---|
POST | /v1/session/init | Create a session (builder-signed) |
GET | /v1/session/{sessionId}/poll | Poll for session completion |
POST | /v1/session/claim | Claim a session (Desktop App) |
POST | /v1/session/{sessionId}/approve | Approve with grant details |
POST | /v1/session/{sessionId}/deny | Deny the request |
POST /v1/session/init request must include an Authorization: Web3Signed header signed by the builder.
Deep links
The Desktop App receives session details via a deep link:Grant payload
When the builder polls and the session is approved, it receives:grantId to make data requests and userAddress to resolve the Personal Server URL via the Gateway.
Onchain contract
Grants are stored onchain in theDataPortabilityPermissions contract.
Address: 0xD54523048AdD05b4d734aFaE7C68324Ebb7373eF (Moksha Testnet)
Data structures
Contract functions
Gateway grant API
The Data Portability RPC (Gateway) provides fast API access to grant operations with eventual chain consistency.| Method | Path | Description |
|---|---|---|
POST | /v1/grants | Create a grant |
DELETE | /v1/grants/{grantId} | Revoke a grant |
GET | /v1/grants/{grantId} | Get grant details |
GET | /v1/grants?user={address} | List grants for a user |
GET | /v1/grants?builder={address} | List grants for a builder |
GET | /v1/grants/{grantId}/status | Get onchain confirmation status |
Nonces
Nonces prevent replay attacks. Before creating a grant, query the current nonce:Builder SDK
The@opendatalabs/connect SDK provides helpers for the Connect Data flow and data access. See Integrate Vana for the full integration guide.
Related
- Personal Servers — Builder data access and Web3Signed authorization
- Scopes & Schemas — What scopes are and how they’re defined
- Identity — Builder registration and the
DataPortabilityGranteescontract - Integrate Vana — Step-by-step builder integration guide