# Getting Started

### How does EyePop.ai work?

You will create endpoints that use a cloud or edge based AI worker server that streamlines your detection tasks. We call these endpoints a “Pop”. Whether you're looking to post images, videos, or even connect through live webrtc, EyePop.ai offers the flexibility and efficiency to suit your requirements.

### Build your first "Pop" Endpoint<br>

EyePop.ai Quickstart Guide

This guide walks you from zero → first working visual intelligence task using EyePop.ai.

***

### What You're Building

You'll create your first **Pop** — a configured worker endpoint that turns images, video, or livestreams into structured predictions (bounding boxes, classes, confidence scores, and more).

Example use cases:

* Classify an image
* Detect objects or events in video
* Process live RTSP / RTMP streams
* Identify behavior (e.g. "person entering")

***

### Step 1 — Create an Account & Get Credentials

1. Sign up at <https://eyepop.ai>
2. In your profile, generate a **Secret API Key** and copy it

* `EYEPOP_API_KEY` — your secret key, used to authenticate

Store them as environment variables (recommended) or pass them explicitly to the SDK.

```bash
export EYEPOP_API_KEY="your-api-key"
```

***

### Step 2 — Install the SDK

#### Python (3.8+)

```bash
pip install eyepop
```

#### Node / React

```bash
npm install --save @eyepop.ai/eyepop
```

#### Browser (CDN)

```html
<script src="https://cdn.jsdelivr.net/npm/@eyepop.ai/eyepop/dist/eyepop.min.js"></script>
```

***

### Step 3 — Connect to Your Pop

The SDK authenticates with your API key and loads the worker configuration for the Pop identified by `EYEPOP_POP_ID`.

#### Python

```python
import os
from eyepop import EyePopSdk

endpoint = EyePopSdk.workerEndpoint(
    secret_key=os.environ.get('EYEPOP_API_KEY'),  # default; can be omitted
)

endpoint.connect()
endpoint.set_pop(<POP_DEFINITION>)
# do work ...
endpoint.disconnect()
```

Or, more idiomatically, use a context manager so resources are cleaned up automatically:

```python
from eyepop import EyePopSdk

with EyePopSdk.workerEndpoint() as endpoint:
    endpoint.set_pop(<POP_DEFINITION>)
    # do work ...
    pass
```

#### Node / TypeScript

```typescript
import { EyePop } from '@eyepop.ai/eyepop'

(async () => {
    const endpoint = await EyePop.workerEndpoint({
        auth: { secretKey: process.env['EYEPOP_API_KEY'] },
    }).connect()
    await client.changePop(<POP_DEFINITION>);

    // do work ...
    await endpoint.disconnect()
})()
```

Shorter form (reads env vars automatically):

```typescript
const endpoint = await EyePop.workerEndpoint().connect()
```

***

### Step 4 — Run Your First Prediction

#### Python — upload a single image

```python
from eyepop import EyePopSdk

def upload_photo(file_path: str):
    with EyePopSdk.workerEndpoint() as endpoint:
        result = endpoint.upload(file_path).predict()
        print(result)

upload_photo('examples/example.jpg')
```

* `endpoint.upload(path)` queues the file for processing.
* `predict()` blocks until the first prediction is available and returns it as a dict.
* For videos or image containers (GIF, etc.), call `predict()` in a loop — one result per frame — until it returns `None`.

#### Python — load from a URL (HTTP, RTSP, or RTMP)

```python
from eyepop import EyePopSdk

with EyePopSdk.workerEndpoint() as endpoint:
    result = endpoint.load_from(
        'https://farm2.staticflickr.com/1080/1301049949_532835a8b5_z.jpg'
    ).predict()
    print(result)
```

#### Node — upload a single image

```typescript
import { EyePop } from '@eyepop.ai/eyepop'

(async () => {
    const endpoint = await EyePop.workerEndpoint().connect()
    try {
        const results = await endpoint.process({ file: 'examples/example.jpg' })
        for await (const result of results) {
            console.log(result)
        }
    } finally {
        await endpoint.disconnect()
    }
})()
```

* `endpoint.process({...})` accepts a `file` path, a `url`, or a readable `stream` with a `mimeType`.
* Results are streamed as an `AsyncIterable<Prediction>` — iterate with `for await`.

#### Node — load from a URL

```typescript
const results = await endpoint.process({
    url: 'https://farm2.staticflickr.com/1080/1301049949_532835a8b5_z.jpg'
})
for await (const result of results) {
    console.log(result)
}
```

***

### Step 5 — Understand the Output

EyePop returns structured JSON, not raw model text. A typical prediction includes the source dimensions and a list of detected objects with bounding boxes, classes, and confidence scores.

Example (shape will vary by Pop configuration):

```json
{
  "source_width": 1280,
  "source_height": 720,
  "seconds": 0.0,
  "objects": [
    {
      "classLabel": "person",
      "confidence": 0.97,
      "x": 420, "y": 180, "width": 160, "height": 340
    }
  ]
}
```

This is easy to plug directly into:

* alerts
* workflows
* dashboards
* automation systems

***

### Step 6 — Process Batches Efficiently

#### Python — synchronous batch

Queue all jobs first, then collect results. This avoids paying the HTTP roundtrip per image.

```python
from eyepop import EyePopSdk

def upload_photos(file_paths: list[str]):
    with EyePopSdk.workerEndpoint() as endpoint:
        jobs = [endpoint.upload(p) for p in file_paths]
        for job in jobs:
            print(job.predict())

upload_photos(['examples/example.jpg'] * 100)
```

#### Python — asynchronous batch (high throughput)

For very large batches, use the async variant with an `on_ready` callback so results are processed as soon as they land.

```python
import asyncio
from eyepop import EyePopSdk, Job

async def async_upload_photos(file_paths: list[str]):
    async def on_ready(job: Job):
        print(await job.predict())

    async with EyePopSdk.workerEndpoint(is_async=True) as endpoint:
        for file_path in file_paths:
            await endpoint.upload(file_path, on_ready)

asyncio.run(async_upload_photos(['examples/example.jpg'] * 100000))
```

#### Node — parallel processing

Don't `await` each call; use `.then()` so uploads run in parallel (up to 5 HTTP connections per endpoint).

```typescript
for (let i = 0; i < 100; i++) {
    endpoint.process({ path: 'examples/example.jpg' }).then(async (results) => {
        for await (const result of results) {
            console.log(`result for #${i}`, result)
        }
    })
}
```

***

### Step 7 — Process Video

The same Pop handles video via upload or public URL — HTTP, RTSP, or RTMP.

#### Python

```python
from eyepop import EyePopSdk

with EyePopSdk.workerEndpoint() as endpoint:
    job = endpoint.load_from(
        'https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4'
    )
    while result := job.predict():
        print(result)
```

#### Node

```typescript
const results = await endpoint.process({
    url: 'https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4'
})
for await (const result of results) {
    console.log(result)
}
```

#### Canceling a job mid-stream

```python
while result := job.predict():
    print(result)
    if result['seconds'] >= 10.0:
        job.cancel()
```

```typescript
for await (const result of results) {
    if (result['seconds'] >= 10.0) {
        results.cancel()
    }
}
```

***

### Step 8 — Process a Live Stream (Browser)

Connect EyePop to a real-time `MediaStream` (e.g. from `getUserMedia`) via `liveIngress`.

```javascript
import { EyePop } from '@eyepop.ai/eyepop'
import Render2d from '@eyepop.ai/eyepop-render-2d'

const setupLiveProcessing = async (canvas, videoStream) => {
    const endpoint = await EyePop.workerEndpoint({
        popId: process.env.NEXT_PUBLIC_POP_ID,
        auth: { secretKey: process.env.NEXT_PUBLIC_API_KEY },
    }).connect()

    const renderer = Render2d.renderer(canvas.getContext('2d'), [
        Render2d.renderBox({ showClass: true, showConfidence: true }),
    ])

    const ingress = await endpoint.liveIngress(videoStream)
    const results = await endpoint.process({ ingressId: ingress.ingressId() })

    for await (const result of results) {
        if (canvas.width !== result.source_width) canvas.width = result.source_width
        if (canvas.height !== result.source_height) canvas.height = result.source_height
        renderer.draw(result)
    }
}
```

> Requires a readable `MediaStream`. If using `getUserMedia`, handle camera permissions and stream lifecycle cleanly.

***

### Step 9 — Visualize Results

#### Python — with matplotlib

```python
from PIL import Image
import matplotlib.pyplot as plt
from eyepop import EyePopSdk

with EyePopSdk.workerEndpoint() as endpoint:
    result = endpoint.upload('examples/example.jpg').predict()

with Image.open('examples/example.jpg') as image:
    plt.imshow(image)

plot = EyePopSdk.plot(plt.gca())
plot.prediction(result)
plt.show()
```

#### Node — with `@eyepop.ai/eyepop-render-2d`

Render bounding boxes and labels onto a canvas. See the `Render2d` usage shown in Step 8.

***

### Step 10 — Authentication Options (Node)

Three patterns, in order of production-readiness:

1. **API Key (server-side only)** — pass `auth: { secretKey }`. Never expose this in client code.
2. **Session token (recommended for browsers)** — generate a short-lived session server-side and hand it to the client.

   ```typescript
   // Server
   const session = await endpoint.session()
   res.json(session)
   ```

   ```typescript
   // Client
   const endpoint = await EyePop.workerEndpoint({ auth: { session } }).connect()
   ```
3. **Current browser session (dev only)** — if the developer is logged into the EyePop Dashboard, use `auth: { oAuth2: true }` with an explicit `popId`.

***

### Step 11 — Deploy On-Premise (Optional)

For local IP-camera workflows, EyePop supports an on-prem architecture: a lightweight app captures and samples frames from RTSP/HTTP cameras, sends selected frames to the EyePop cloud for inference, and triggers notifications (Twilio, SendGrid, Slack, webhooks). Images can optionally be archived locally for audit or dataset curation.

Benefits:

* Low-latency local dashboard
* Cloud offload for heavy inference (stateless, no server-side storage)
* Pluggable alerting
* Audit-ready image archive

See the [On-Premise IP Camera Analysis](https://docs.eyepop.ai/developer-documentation/deployment/on-premise-ip-camera-analysis) deployment guide.

***

### Tuning Tips

* **Auto-start workers:** `EyePopSdk.endpoint(auto_start=False)` (Python) / `EyePop.endpoint({ autoStart: false })` (Node) disables automatic worker startup on `connect()`.
* **Preserve pending jobs:** by default, `connect()` cancels queued jobs on the worker. Pass `stop_jobs=False` / `stopJobs: false` to keep them.
* **Keep API keys out of source control:** use `python-dotenv` or Node's `dotenv` with a `.env` file.
* **Override the API URL:** set `EYEPOP_URL` if you're pointing at a non-production endpoint.

***

### Next Steps

* Build a small evaluation set (20–100 images) and iterate
* Chain predictions into a workflow (e.g. detect → crop → classify)
* Move from cloud API to on-prem when latency or data-residency demands it

***

### Need Help?

* Docs: <https://docs.eyepop.ai>
* Dashboard: <https://dashboard.eyepop.ai>
* Python SDK: <https://github.com/eyepop-ai/eyepop-sdk-python>
* Node SDK: <https://github.com/eyepop-ai/eyepop-sdk-node>
* Example projects: <https://github.com/eyepop-ai/Labs>

Or reach out for help scoping your first production use case.<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eyepop.ai/developer-documentation/getting-started.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
