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

# Search Sessions

> Maximize your lookups with search sessions - the preferred way to search

## What are Search Sessions?

Search sessions are a way to **maximize the value of each lookup** in your plan. When you initialize a search session, you can perform multiple searches across different services (breach, stealer, OSINT) for the **same query** while only consuming a single lookup from your daily quota.

<Note>
  The same `search_id` flow works with simple GET requests, POST-based structured filters, investigation search, victim details, file metadata, Phonebook, and raw file/text downloads.
</Note>

<Card title="View Plan Quotas" icon="coins" href="https://oathnet.org/pricing">
  Check how many lookups are included in each plan
</Card>

## Why Use Search Sessions?

<Warning>
  **Without a search session:** Each API call deducts 1 lookup from your daily quota.

  **With a search session:** Multiple calls for the same query consume only 1 lookup (within the session quota).
</Warning>

### Example Comparison

| Scenario                              | Without Session | With Session             |
| ------------------------------------- | --------------- | ------------------------ |
| Search breach for `user@example.com`  | 1 lookup        | 1 lookup                 |
| Search stealer for `user@example.com` | 1 lookup        | 0 lookups (same session) |
| Discord lookup                        | 1 lookup        | 0 lookups (same session) |
| **Total**                             | **3 lookups**   | **1 lookup**             |

Each plan has a **session quota** that determines how many searches you can perform within a single session. See [pricing](https://oathnet.org/pricing) for details.

## Creating a Session

Initialize a session before making related queries:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://oathnet.org/api/service/search/init" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "user@example.com",
      "search_type": "email"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://oathnet.org/api/service/search/init",
      headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
      json={"query": "user@example.com", "search_type": "email"}
  )

  session = response.json()["data"]["session"]
  session_id = session["id"]
  print(f"Session ID: {session_id}")
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://oathnet.org/api/service/search/init", {
    method: "POST",
    headers: {
      "x-api-key": API_KEY,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ query: "user@example.com", search_type: "email" })
  });

  const { data: { session } } = await response.json();
  console.log(`Session ID: ${session.id}`);
  ```
</CodeGroup>

## Using a Session

Pass the session ID using the `search_id` parameter to subsequent API calls:

```python theme={null}
session_id = "sess_1234567890abcdef"

# All these searches use the same session = 1 lookup total
breach_results = requests.get(
    "https://oathnet.org/api/service/v2/breach/search",
    params={"q": "user@example.com", "search_id": session_id},
    headers={"x-api-key": API_KEY}
).json()

stealer_results = requests.get(
    "https://oathnet.org/api/service/v2/stealer/search",
    params={"q": "user@example.com", "search_id": session_id},
    headers={"x-api-key": API_KEY}
).json()
```

## Multi-Section Investigation Example

Create a session first, then send a multi-section investigation request. This lets one flow ask for credentials, victims, evidence, files, and related credentials together.

```python theme={null}
session = requests.post(
    "https://oathnet.org/api/service/search/init",
    headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
    json={"query": "example.com", "search_type": "domain"},
).json()["data"]["session"]

investigation = requests.post(
    "https://oathnet.org/api/service/v2/stealer/investigation/search",
    headers={"x-api-key": API_KEY, "Content-Type": "application/json"},
    json={
        "q": "example.com",
        "search_id": session["id"],
        "scope": "all",
        "include": ["credentials", "victims", "evidence", "files", "related_credentials"],
        "compact": True,
        "view": "enriched",
        "page_size": 25,
        "filters": {
            "credentials": {"domain": ["example.com"], "has_log_id": True},
            "victims": {"service": ["discord"], "country": ["US"]},
            "evidence": {"service": "discord", "confidence": ["high"]},
            "files": {"kind": "cookies"},
        },
    },
).json()
```

Keep each section separate in your UI or script. Use `links` to explain relationships between credentials, victims, evidence, and files.

## Smart Query Detection

The `q` parameter uses **smart query detection** to automatically determine the type of your search:

<Note>
  **Highlighted Feature:** You don't need to specify the query type - OathNet automatically detects it based on the format of your query.
</Note>

| Query Format            | Detected Type | Example              |
| ----------------------- | ------------- | -------------------- |
| Contains `@` and domain | `email`       | `user@example.com`   |
| Valid domain format     | `domain`      | `example.com`        |
| IPv4 or IPv6 address    | `ip`          | `192.168.1.1`        |
| 14-19 digit number      | `discord_id`  | `123456789012345678` |
| 17-digit number         | `steam_id`    | `76561198012345678`  |
| Other alphanumeric      | `username`    | `john_doe_123`       |

## Session Duration

* Sessions are valid for **60 minutes** from creation
* After expiration, you need to create a new session
* Each new session for a different query consumes a lookup

## Without Sessions (Not Recommended)

You can make API calls without initializing a session first:

```python theme={null}
# Works, but each call deducts 1 lookup
response = requests.get(
    "https://oathnet.org/api/service/v2/breach/search",
    params={"q": "user@example.com"},
    headers={"x-api-key": API_KEY}
)
```

<Warning>
  This approach is **not recommended** as you'll consume more lookups from your quota. Always use search sessions for better value.
</Warning>

## Quota Reset

Your daily lookup quota resets **24 hours** after your first lookup of the day.

## Best Practices

<AccordionGroup>
  <Accordion title="Always Initialize Sessions" icon="play">
    For any investigation, always start with a session:

    ```python theme={null}
    # Step 1: Initialize session
    session = init_session("target@example.com")

    # Step 2: Use session for all related searches
    search_breach(session["id"])
    search_stealer(session["id"])
    lookup_discord(session["id"])
    ```
  </Accordion>

  <Accordion title="One Session Per Query" icon="folder">
    Create a new session for each distinct query you're investigating:

    ```python theme={null}
    # Investigation 1
    session1 = init_session("user1@example.com")

    # Investigation 2 (different query = new session)
    session2 = init_session("user2@example.com")
    ```
  </Accordion>

  <Accordion title="Reuse Within Time Window" icon="clock">
    Sessions last 60 minutes - reuse them for follow-up searches on the same query:

    ```python theme={null}
    session = init_session("user@example.com")

    # Initial search
    breach_results = search_breach(session["id"])

    # Later (within 60 min) - still uses same session
    more_results = search_stealer(session["id"])
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Pagination" icon="page" href="/guides/pagination">
    Handle large result sets
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/guides/error-handling">
    Handle errors gracefully
  </Card>
</CardGroup>
