New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@opendatalabs/connect-js

Package Overview
Dependencies
Maintainers
4
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opendatalabs/connect-js

JavaScript SDK for embedding Open Data Labs Connect flows

npmnpm
Version
1.19.0-dev.6
Version published
Weekly downloads
24
20%
Maintainers
4
Weekly downloads
 
Created
Source

@opendatalabs/connect-js

JavaScript SDK for launching Open Data Labs Connect and reading the selected data from the user's Personal Server.

The v2 flow uses the same trust split as Plaid Link or Stripe Connect:

  • your backend holds the Open Data Labs API key
  • your backend chooses the source and scopes
  • your frontend opens Vana in a second tab and keeps your app tab alive
  • after the user approves, your backend reads the approved scopes from the user's Personal Server

The redirect is a navigation and correlation signal, not data delivery. The browser entry point has no API key. Keep session status and data reads behind your backend routes.

Installation

npm install @opendatalabs/connect-js

Backend

// lib/odl.ts
import { createConnectController } from "@opendatalabs/connect-js/server";

export const odl = createConnectController({
  apiBaseUrl: process.env.ODL_API_BASE_URL!,
  apiKey: process.env.ODL_API_KEY!,
  appId: process.env.ODL_APP_ID!,
  defaultOrigin: process.env.APP_URL ?? "https://your-app.com",
  source: "instagram",
  scopes: ["read:profile", "read:posts"],
});
// app/api/connect/session/route.ts
import { odl } from "@/lib/odl";

export async function POST() {
  return Response.json(
    await odl.createConnectSession({
      redirectUrl: `${process.env.APP_URL ?? "https://your-app.com"}/connect/return`,
    })
  );
}
// app/api/connect/status/route.ts
import { odl } from "@/lib/odl";

export async function GET(request: Request) {
  const connectionId = new URL(request.url).searchParams.get("connectionId");
  if (!connectionId) {
    return Response.json({ error: "Missing connectionId" }, { status: 400 });
  }
  return Response.json(await odl.getStatus(connectionId));
}
// app/api/connect/data/route.ts
import { odl } from "@/lib/odl";

export async function GET(request: Request) {
  const connectionId = new URL(request.url).searchParams.get("connectionId");
  if (!connectionId) {
    return Response.json({ error: "Missing connectionId" }, { status: 400 });
  }
  return Response.json(await odl.readAllWhenReady(connectionId));
}

Use ready_for_read as the read gate, not completed. The backend readAllWhenReady() helper reads every requested scope and completes only after the final scope drives the Vana acknowledgement. One successful scope read is not complete. If acknowledgement fails, it raises a retryable typed ConnectError with kind vana_ack_failed instead of reporting partial success.

React

import { useTwoTabConnect } from "@opendatalabs/connect-js/react";

export function ConnectButton() {
  const connect = useTwoTabConnect({
    openingUrl: process.env.NEXT_PUBLIC_VANA_CONNECT_OPENING_URL,
    createSession: async () => {
      const res = await fetch("/api/connect/session", { method: "POST" });
      if (!res.ok) throw new Error("Failed to create Connect session");
      return res.json();
    },
    getStatus: async (connectionId) => {
      const res = await fetch(
        `/api/connect/status?connectionId=${encodeURIComponent(connectionId)}`
      );
      if (!res.ok) throw new Error("Failed to fetch Connect status");
      return res.json();
    },
    readResult: async (connectionId) => {
      const res = await fetch(
        `/api/connect/data?connectionId=${encodeURIComponent(connectionId)}`
      );
      if (!res.ok) throw new Error("Failed to read Connect data");
      return res.json();
    },
  });

  return (
    <button disabled={connect.state.type !== "idle"} onClick={() => connect.start()} type="button">
      {connect.state.type === "idle" ? "Connect data" : "Connecting..."}
    </button>
  );
}

useTwoTabConnect opens a Vana-hosted holding page synchronously inside the click event, then redirects that tab to the Connect approval page after your backend creates the session. This avoids popup blockers without showing users a blank about:blank tab.

The default holding page is https://app.vana.org/connect/opening. For dev or staging, set NEXT_PUBLIC_VANA_CONNECT_OPENING_URL to the matching Vana app, for example https://app-dev.vana.org/connect/opening.

Source IDs

Use stable source IDs such as instagram or icloud_notes, not display names such as "Instagram" or "iCloud Notes".

Requirements

  • Keep your API key on the server.
  • Choose source and scopes on the server.
  • Add each app domain in the dashboard before creating sessions for it.
  • Keep the Vana tab open while your app reads from the user's Personal Server.
  • Use ready_for_read as the read gate. completed follows the reads and acknowledgement.

FAQs

Package last updated on 14 Aug 2026

Related posts