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

# Quickstart

> Connect your first user and read their conversations.

## Before you start

Onboarding gives you four values. Write to [hello@tryverso.ai](mailto:hello@tryverso.ai) to get them.

| Value | Looks like | Used for |
| - | - | - |
| App id | `app_yourapp` | Identifies your app in links and API calls |
| App secret | random string | `signLink()` only. Never send it as a Bearer token. |
| API key | `vsk_…` | `Authorization: Bearer` on every API call |
| Webhook secret | random string | `verifyWebhook()` on incoming deliveries |

You also need Node.js 20 or newer for the SDK, and a public HTTPS endpoint for webhooks.

## 1. Install the SDK

```bash theme={null}
npm install @versoai/core
```

## 2. Send the user to the connect page

Sign a link on your backend and redirect the user to it. Collect the user's consent in your own UI before this step: the hosted page goes straight to the provider's login.

```typescript theme={null}
import { signLink } from "@versoai/core";

const { url } = await signLink(
  {
    appId: "app_yourapp",
    userRef: user.id,               // your identifier for this user, returned in every webhook
    scopes: ["conversations:read"],
    purpose: "connect",
  },
  process.env.VERSO_APP_SECRET!,
);

res.redirect(url);                  // https://connect.tryverso.ai/start?token=…
```

The link expires after 15 minutes and works once. If the user abandons the page, sign a new one.

## 3. Receive webhooks

Verso posts signed JSON to your webhook URL. Verify the signature on the raw body, then act on the typed event.

```typescript theme={null}
import express from "express";
import { verifyWebhook } from "@versoai/core";
import type { WebhookEvent } from "@versoai/core";

const app = express();

app.post("/webhooks/verso", express.raw({ type: "application/json" }), (req, res) => {
  const body = req.body.toString("utf8");
  const signature = req.get("x-verso-signature") ?? "";

  if (!verifyWebhook(process.env.VERSO_WEBHOOK_SECRET!, signature, body)) {
    return res.status(401).send("Bad signature");
  }

  const event = JSON.parse(body) as WebhookEvent;

  switch (event.event) {
    case "connection.created":
      // event.payload.userRef is connected; syncing has started
      break;
    case "reauth.needed":
      // send event.payload.userRef a new connect link
      break;
    case "data.imported":
      // event.payload.inserted new conversations for event.payload.userRef
      break;
  }

  res.sendStatus(200);
});
```

Respond with any 2xx within 10 seconds. Deliveries are retried on failure, so use `deliveryId` to ignore duplicates.

## 4. Check a user's status

```bash theme={null}
curl -s "https://connect.tryverso.ai/api/connections?userRef=user_123" \
  -H "Authorization: Bearer $VERSO_API_KEY"
```

```json theme={null}
{
  "userRef": "user_123",
  "connected": true,
  "needsReauth": false,
  "recentConversationCount": 12,
  "recentWindowDays": 30,
  "connections": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "provider": "chatgpt",
      "status": "active",
      "capturedAt": "2026-09-20T10:00:00Z",
      "lastSyncAt": "2026-09-29T14:41:11Z",
      "conversationCount": 142,
      "recentConversationCount": 12
    }
  ]
}
```

`connected` means at least one connection is syncing. `needsReauth` means the user has to connect again. `recentConversationCount` is the number of conversations the user started in the last 30 days.

## 5. Read conversations

```bash theme={null}
curl -s "https://connect.tryverso.ai/api/conversations?connectionId=550e8400-e29b-41d4-a716-446655440000&limit=100" \
  -H "Authorization: Bearer $VERSO_API_KEY"
```

```json theme={null}
{
  "conversations": [
    {
      "id": "6a1f…",
      "external_id": "68d9c2a1-3f0e-8005-b2c1-7e2f0d1a9b3c",
      "title": "Help me build a REST API",
      "update_time": "2026-09-20T10:05:00Z",
      "payload": {
        "title": "Help me build a REST API",
        "messages": [
          { "role": "user", "content": "I need a REST API for managing tasks…", "timestamp": "2026-09-20T10:00:00.000Z" },
          { "role": "assistant", "content": "I'll help you build a task management API…", "timestamp": "2026-09-20T10:00:05.000Z", "model": "gpt-4o" }
        ]
      }
    }
  ],
  "total": 142,
  "limit": 100,
  "offset": 0
}
```

## 6. What happens next

* The first sync runs within a minute of the connection and imports the most recent conversations. Older history is backfilled over the following hours, at the pace the provider allows.
* Later syncs run every 4 hours after activity, and less often for idle accounts, up to every 48 hours. Each sync that changes something sends `data.imported`.
* When the provider rejects the stored session, the connection becomes `needs_reauth` and you receive `reauth.needed`. Sign a new connect link for the user.
* To let the user see and delete their data, sign a link with `purpose: "manage"`.

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/guides/authentication">Signed links, API keys, rate limits.</Card>
  <Card title="Connect flow" icon="plug" href="/guides/connect-flow">What the user sees and what Verso does.</Card>
  <Card title="Webhooks" icon="bell" href="/guides/webhooks">Every event, with payloads.</Card>
  <Card title="Data management" icon="database" href="/guides/data-management">Status, activity, reading and sync cadence.</Card>
</CardGroup>
