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

# Verification Sessions

> Create v2 verification sessions, redirect users, and read completion through polling or Server-Sent Events.

Verification sessions let your app start a Dock verification flow and receive the completed Discord to Roblox link without webhooks.

## Flow

**1. Create a session**

Call `POST /v2/sessions` with your `pid`, your internal `clientId`, and optional `guildId`.

**2. Redirect the user**

Send the user to `data.verifyUrl`.

**3. Wait for completion**

Read `GET /v2/sessions/:id?wait=25` or open `GET /v2/sessions/:id/stream`.

**4. Store the result**

When `status` becomes `completed`, store `result.discordId`, `result.robloxId`, and your original `clientId`.

```mermaid theme={null}
sequenceDiagram
  participant App
  participant Dock
  participant User

  App->>Dock: POST /v2/sessions
  Dock-->>App: id, clientId, verifyUrl
  App->>User: Redirect to verifyUrl
  User->>Dock: Complete verification
  App->>Dock: GET /v2/sessions/:id?wait=25
  Dock-->>App: completed result
```

## Create a session

```http theme={null}
POST /v2/sessions
```

**pid** `string` *required*

Public Identifier attached to your API key. The `pid` must belong to the authenticated API key.

**clientId** `string` *required*

Your internal user, session, or checkout ID. Dock returns it with the session so you can map completion back to your system.

**guildId** `string`

Optional Discord guild ID for flows that need guild context.

**Idempotency-Key** `string`

Optional key for safely retrying session creation with the same body.

```bash cURL theme={null}
curl --request POST \
  --url "https://api.docksys.xyz/v2/sessions" \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: verify-user-123" \
  --data '{
    "pid": "PID-ABC12345",
    "clientId": "user_123",
    "guildId": "987654321098765432"
  }'
```

```json 200 OK theme={null}
{
  "status": 200,
  "data": {
    "id": "vsn_A1b2C3d4E5f6G7h8J9k0L1",
    "pid": "PID-ABC12345",
    "clientId": "user_123",
    "guildId": "987654321098765432",
    "status": "pending",
    "statusReason": null,
    "expiresAt": "2026-05-07T00:05:00.000Z",
    "verifyUrl": "https://api.docksys.xyz/v2/verifications/discord?pid=PID-ABC12345&sid=vsn_A1b2C3d4E5f6G7h8J9k0L1",
    "reusedExisting": false
  },
  "meta": {
    "requestId": "req_abc123",
    "version": "2.0.0"
  },
  "timestamp": "2026-05-07T00:00:00.000Z"
}
```

## Read a session

```http theme={null}
GET /v2/sessions/:id
```

**id** `string` *required*

Session ID returned as `data.id` by session creation.

**wait** `number`

Optional long-poll wait in seconds. Maximum `25`.

```bash Long-poll theme={null}
curl --request GET \
  --url "https://api.docksys.xyz/v2/sessions/vsn_A1b2C3d4E5f6G7h8J9k0L1?wait=25" \
  --header "Authorization: Bearer YOUR_API_KEY"
```

## Stream a session

```http theme={null}
GET /v2/sessions/:id/stream
```

The stream uses Server-Sent Events and sends `session` events. The connection closes when the session reaches a terminal state or after the stream limit.

```javascript Browser or Node SSE theme={null}
const source = new EventSource(
  "https://api.docksys.xyz/v2/sessions/vsn_A1b2C3d4E5f6G7h8J9k0L1/stream",
);

source.addEventListener("session", (event) => {
  const session = JSON.parse(event.data);

  if (session.status === "completed") {
    console.log(session.result);
    source.close();
  }
});
```

> [!NOTE]
>
> Browser `EventSource` cannot set custom Authorization headers. If you need API-key auth from a browser, proxy the stream through your backend.

## Session states

| State | Meaning |
| - | - |
| `pending` | The user has not completed verification yet. |
| `completed` | Verification completed and `result` is populated. |
| `expired` | The session reached its 5-minute lifetime before completion. |

## Completed result

```json Completed session theme={null}
{
  "id": "vsn_A1b2C3d4E5f6G7h8J9k0L1",
  "pid": "PID-ABC12345",
  "clientId": "user_123",
  "guildId": "987654321098765432",
  "status": "completed",
  "statusReason": null,
  "createdAt": "2026-05-07T00:00:00.000Z",
  "expiresAt": "2026-05-07T00:05:00.000Z",
  "terminalAt": "2026-05-07T00:01:12.000Z",
  "verifyUrl": "https://api.docksys.xyz/v2/verifications/discord?pid=PID-ABC12345&sid=vsn_A1b2C3d4E5f6G7h8J9k0L1",
  "result": {
    "discordId": "123456789012345678",
    "robloxId": "156319135",
    "verifiedAt": "2026-05-07T00:01:12.000Z",
    "linkChanged": false,
    "previousRobloxId": null,
    "linkVersion": 1,
    "linkHash": "sha256-link-marker"
  }
}
```

**result.linkChanged** `boolean`

`true` when the same Discord user was previously linked to a different Roblox account in your PID dataset.

**result.previousRobloxId** `string | null`

Previous Roblox ID when `linkChanged` is `true`.

## Limits

| Guardrail | Value |
| - | - |
| Session lifetime | 5 minutes |
| Create burst | 6 sessions |
| Create refill | 1 session every 10 seconds |
| Minimum poll interval | 2 seconds |
| Maximum `wait` | 25 seconds |
| Stream max duration | 30 seconds |
| Free poll cap | 60 polls |
| Premium poll cap | 150 polls |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.