Skip to main content
source identifies the connected data source, for example icloud_notes. scopes identify approved data sets, for example ["icloud_notes.notes"]. Start with a source listed in the Vana app at app.vana.org/sources. For the current supported source and scope list, see the data-connectors scope registry: PDP-Connect/data-connectors/SCOPES.md.
Need a source that isn’t available yet? See Add a connector.
A new approval adds to what your app already holds. A grant is keyed by the (user, app) pair, so a user holds one grant per app. When the user approves a new request, the Vana approval page signs the scopes your app already holds plus the new ones. Earlier scopes stay readable. This needs @opendatalabs/vana-sdk 4.3.0 or later.One source per request. A request targets one source. Scopes from another source in the same request (for example an icloud_notes.* scope with a spotify.* scope) read empty, because the approval connects only one source. If your app needs several sources, run one approval per source. The grant ends up holding the scopes of every source the user approved.Request a source’s scopes together. Put every scope your app needs from one source in the scopes array of a single request, so the user approves that source once.

Use two sources

Create one controller per source, with the same app key and app identity, and run one approval for each:
lib/vana.ts
Give each controller its own request, status and data routes (for example /api/vana/oura/* and /api/vana/spotify/*) and its own connect button. Each approval returns its own requestId; read each source with its controller. Drop a scope on purpose. To give up a scope your app holds, pass it in removeScopes (SDK 4.3.0 or later):

Reading more than one scope

Approving several scopes and reading several scopes are separate steps. getAccessRequestStatus returns the full approved set as scopes, and scope as the first of them:
readApprovedData reads one scope — the first approved scope unless you name another. To read everything the user approved, use readAllApprovedData:
Each scope is a separate paid read. Requesting five scopes costs the same as requesting one — a grant is registered once. But reading five scopes settles five data_access fees, so read only what your app uses.Acknowledgement is terminal. A successful readApprovedData acknowledges the request and moves it to completed, which is no longer readable. If you loop over scopes yourself, pass acknowledge: false on every call but the last. readAllApprovedData handles this for you — it acknowledges once, after the final scope, and only if every scope read. A scope that fails lands in errors and leaves the request unacknowledged so you can retry it.