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

# Installation

> Get started with Pixel Patrol in your application

## Overview

Pixel Patrol can be integrated into any application through our REST API. This guide covers installation options, authentication setup, and basic configuration.

## Integration Methods

### REST API

The primary integration method for all platforms:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pixelpatrol.net/functions/v1/submit-media \
    -H "Content-Type: application/json" \
    -d '{
      "api_key": "site_xxxxxxxxxxxxxxxxxxxx",
      "content_url": "https://example.com/image.jpg",
      "app_media_id": "unique-media-id-123"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.pixelpatrol.net/functions/v1/submit-media",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        api_key: "site_xxxxxxxxxxxxxxxxxxxx",
        content_url: "https://example.com/image.jpg",
        app_media_id: "unique-media-id-123",
      }),
    }
  );
  ```

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

  response = requests.post(
    'https://api.pixelpatrol.net/functions/v1/submit-media',
    headers={
      'Content-Type': 'application/json'
    },
    json={
      'api_key': 'site_xxxxxxxxxxxxxxxxxxxx',
      'content_url': 'https://example.com/image.jpg',
      'app_media_id': 'unique-media-id-123'
    }
  )
  ```
</CodeGroup>

### SDKs (Coming Soon)

Official SDKs in development:

* JavaScript/TypeScript
* Python
* PHP
* Ruby
* Go
* Java

## Authentication Setup

### Getting Your Site Key

1. Sign up at [pixelpatrol.net](https://app.pixelpatrol.net)
2. Create your team
3. Create a site
4. Copy the site key from site settings

### Storing Site Keys

<Warning>
  Never expose site keys in client-side code or public repositories
</Warning>

Best practices for site key storage:

<Tabs>
  <Tab title="Environment Variables">
    ```bash theme={null}
    # .env file
    PIXELPATROL_SITE_KEY=site_xxxxxxxxxxxxxxxxxxxx
    ```

    ```javascript theme={null}
    const apiKey = process.env.PIXELPATROL_SITE_KEY;
    ```
  </Tab>

  <Tab title="Secrets Manager">
    ```javascript theme={null}
    // AWS Secrets Manager
    const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");

    const client = new SecretsManagerClient();
    const response = await client.send(
      new GetSecretValueCommand({
        SecretId: "pixelpatrol-site-key"
      })
    );
    ```
  </Tab>

  <Tab title="Key Vault">
    ```javascript theme={null}
    // Azure Key Vault
    const { SecretClient } = require("@azure/keyvault-secrets");
    const { DefaultAzureCredential } = require("@azure/identity");

    const client = new SecretClient(vaultUrl, new DefaultAzureCredential());
    const secret = await client.getSecret("pixelpatrol-site-key");
    ```
  </Tab>
</Tabs>

## Basic Configuration

### Initialize Client

Create a reusable client configuration:

<CodeGroup>
  ```javascript JavaScript theme={null}
  class PixelPatrolClient {
    constructor(apiKey, options = {}) {
      this.apiKey = apiKey;
      this.baseUrl = options.baseUrl || 'https://api.pixelpatrol.net/functions/v1';
      this.timeout = options.timeout || 30000;
    }

  async submitMedia(mediaData) {
  const response = await fetch(`${this.baseUrl}/submit-media`, {
  method: 'POST',
  headers: {
  'Content-Type': 'application/json'
  },
  body: JSON.stringify({
  api_key: this.apiKey,
  ...mediaData
  }),
  timeout: this.timeout
  });

      if (!response.ok) {
        throw new Error(`API error: ${response.status}`);
      }

      return response.json();

  }
  }

  const client = new PixelPatrolClient(process.env.PIXELPATROL_SITE_KEY);

  ```

  ```python Python theme={null}
  import requests
  from typing import Optional, Dict, Any

  class PixelPatrolClient:
      def __init__(self, api_key: str, base_url: Optional[str] = None, timeout: int = 30):
          self.api_key = api_key
          self.base_url = base_url or 'https://api.pixelpatrol.net/functions/v1'
          self.timeout = timeout
          self.session = requests.Session()
          self.session.headers.update({
              'Content-Type': 'application/json'
          })

      def submit_media(self, media_data: Dict[str, Any]) -> Dict[str, Any]:
          payload = {
              'api_key': self.api_key,
              **media_data
          }
          response = self.session.post(
              f'{self.base_url}/submit-media',
              json=payload,
              timeout=self.timeout
          )
          response.raise_for_status()
          return response.json()

  client = PixelPatrolClient(os.environ['PIXELPATROL_SITE_KEY'])
  ```
</CodeGroup>

## Framework Integration

### Next.js

```javascript theme={null}
// app/api/moderate/route.js
import { NextResponse } from "next/server";

export async function POST(request) {
  const body = await request.json();

  const response = await fetch(
    "https://api.pixelpatrol.net/functions/v1/submit-media",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        api_key: process.env.PIXELPATROL_SITE_KEY,
        content_url: body.imageUrl,
        app_media_id: body.mediaId,
        metadata: body.metadata,
      }),
    }
  );

  const result = await response.json();
  return NextResponse.json(result);
}
```

### Express.js

```javascript theme={null}
const express = require("express");
const app = express();

app.post("/moderate", async (req, res) => {
  try {
    const response = await fetch(
      "https://api.pixelpatrol.net/functions/v1/submit-media",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          api_key: process.env.PIXELPATROL_SITE_KEY,
          ...req.body,
        }),
      }
    );

    const result = await response.json();
    res.json(result);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
```

### Django

```python theme={null}
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import requests
import json

@csrf_exempt
def moderate_content(request):
    if request.method == 'POST':
        data = json.loads(request.body)

        response = requests.post(
            'https://api.pixelpatrol.net/functions/v1/submit-media',
            headers={
                'Content-Type': 'application/json'
            },
            json={
                'api_key': settings.PIXELPATROL_SITE_KEY,
                **data
            }
        )

        return JsonResponse(response.json())
```

## Error Handling

### Common Errors

Implement proper error handling:

```javascript theme={null}
try {
  const result = await client.submitMedia(mediaData);
} catch (error) {
  if (error.status === 401) {
    console.error("Invalid site key");
  } else if (error.status === 429) {
    console.error("Rate limit exceeded");
  } else if (error.status === 400) {
    console.error("Invalid request:", error.message);
  } else {
    console.error("Unexpected error:", error);
  }
}
```

### Retry Logic

Implement exponential backoff:

```javascript theme={null}
async function submitWithRetry(mediaData, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.submitMedia(mediaData);
    } catch (error) {
      if (error.status === 429 || error.status >= 500) {
        const delay = Math.pow(2, i) * 1000;
        await new Promise((resolve) => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error("Max retries exceeded");
}
```

## Testing

### Test Environment

Use test mode for development:

```javascript theme={null}
const client = new PixelPatrolClient(process.env.PIXELPATROL_TEST_SITE_KEY, {
  baseUrl: "https://your-test-supabase-url.supabase.co/functions/v1",
});
```

### Mock Responses

For unit testing:

```javascript theme={null}
// __mocks__/pixelpatrol.js
export const mockSubmitMedia = jest.fn().mockResolvedValue({
  id: "media_123",
  status: "pending",
  message: "Media submitted successfully and queued for moderation.",
});
```

## Next Steps

After installation:

1. [Configure your first site](/getting-started/create-your-site)
2. [Set up moderation rules](/concepts/rules)
3. [Implement webhooks](/features/webhook-notifications)
4. [Test the integration](/api-reference/introduction)

## Support

Need help with installation?

* 📖 [API Documentation](/api-reference/introduction)
* 💬 [Community Forum](https://community.pixelpatrol.net)
* 📧 [Email Support](mailto:support@pixelpatrol.net)
