# Fetch the Verdict

Your backend fetches each session's verdict from Octet, server to server, with a read token. See [Credentials](/docs/browser/integration/credentials/) for how to mint one.

## The request

```bash
curl -s "https://geo.octetproof.com/v1/verdict/$SESSION_REF?waitMs=5000" \
  -H "Authorization: Bearer $OCTET_READ_TOKEN"
```

| Part | Value |
|---|---|
| Method and path | `GET /v1/verdict/{sessionRef}` on `https://geo.octetproof.com` |
| `Authorization` | `Bearer octet_read_...`, your read token |
| `waitMs` | Optional. How long Octet waits for the verdict to arrive before answering, in milliseconds, from `0` to `10000`. Values above `10000` are treated as `10000`. The default is `0`, which answers at once. |

## The responses

**`200`**: the verdict.

```json
{
  "country": "DE",
  "confidence": 0.91,
  "alarm": "none",
  "token": "eyJhbGciOiJFZERTQSIsInR5cCI6Im9jdGV0LWJyb3dzZXItdmVyZGljdCtqd3Q7dj0xIi..."
}
```

Every field is described in [Verdict Reference](/docs/browser/reference/verdict/). `token` is the signed copy of the verdict. See [Verify the Signed Token](/docs/browser/integration/verify-token/).

**`404`**: no verdict for this `sessionRef`.

```json
{ "status": "pending", "ref": "Vq3n0m6c2x6J5aZ8yP1tQw" }
```

Octet answers `404` in any of these cases:

- The session hasn't reached Octet yet. Retry with a `waitMs`.
- The verdict is more than 2 minutes old and has been discarded.
- The `sessionRef` is wrong, or the collector never ran.
- The session arrived under a different license from your read token's license.

**`401`**: the read token was refused. The body names the reason, for example `{ "error": "expired" }`. See [Errors](/docs/browser/reference/errors/).

## How long a verdict lasts

Octet holds each verdict for 2 minutes after the session reaches it. Within that time you can fetch it as often as you like, and each `200` carries a freshly signed `token`. After 2 minutes the fetch returns `404`.

Octet stores the first verdict for a `sessionRef` and keeps it until it expires. A second collection with the same `sessionRef` within those 2 minutes doesn't replace it. Use a new `sessionRef` for each page view. See [The session reference](/docs/browser/concepts/how-it-works/#the-session-reference).

## Node.js

Node.js 18 or later, with no dependencies:

```js
const OCTET = 'https://geo.octetproof.com';

export async function fetchVerdict(sessionRef) {
  const url = `${OCTET}/v1/verdict/${encodeURIComponent(sessionRef)}?waitMs=5000`;
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.OCTET_READ_TOKEN}` },
    signal: AbortSignal.timeout(8000),
  });
  if (res.status === 404) return null; // no verdict: treat as unknown
  if (!res.ok) throw new Error(`octet verdict fetch failed: ${res.status} ${await res.text()}`);
  return res.json();
}
```

## Python

Python 3.9 or later, with `requests`:

```python
import os
import urllib.parse

import requests

OCTET = "https://geo.octetproof.com"


def fetch_verdict(session_ref: str):
    url = f"{OCTET}/v1/verdict/{urllib.parse.quote(session_ref, safe='')}"
    res = requests.get(
        url,
        params={"waitMs": 5000},
        headers={"Authorization": f"Bearer {os.environ['OCTET_READ_TOKEN']}"},
        timeout=8,
    )
    if res.status_code == 404:
        return None  # no verdict: treat as unknown
    res.raise_for_status()
    return res.json()
```

Set your HTTP client's timeout longer than `waitMs`, as both examples do.

## Apply your policy

Decide what a missing verdict means before you go live. For a regulated action, treat it like a masked connection. See [Verdicts](/docs/browser/concepts/verdicts/) for a policy example.
